Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_action.h238
-rw-r--r--source/blender/blenkernel/BKE_anim.h52
-rw-r--r--source/blender/blenkernel/BKE_armature.h121
-rw-r--r--source/blender/blenkernel/BKE_bad_level_calls.h143
-rw-r--r--source/blender/blenkernel/BKE_blender.h64
-rw-r--r--source/blender/blenkernel/BKE_bmfont.h64
-rw-r--r--source/blender/blenkernel/BKE_bmfont_types.h61
-rw-r--r--source/blender/blenkernel/BKE_booleanops.h143
-rw-r--r--source/blender/blenkernel/BKE_booleanops_mesh.h122
-rw-r--r--source/blender/blenkernel/BKE_constraint.h64
-rw-r--r--source/blender/blenkernel/BKE_curve.h86
-rw-r--r--source/blender/blenkernel/BKE_deform.h50
-rw-r--r--source/blender/blenkernel/BKE_displist.h117
-rw-r--r--source/blender/blenkernel/BKE_effect.h65
-rw-r--r--source/blender/blenkernel/BKE_endian.h46
-rw-r--r--source/blender/blenkernel/BKE_exotic.h54
-rw-r--r--source/blender/blenkernel/BKE_font.h50
-rw-r--r--source/blender/blenkernel/BKE_global.h224
-rw-r--r--source/blender/blenkernel/BKE_group.h58
-rw-r--r--source/blender/blenkernel/BKE_ika.h59
-rw-r--r--source/blender/blenkernel/BKE_image.h67
-rw-r--r--source/blender/blenkernel/BKE_ipo.h101
-rw-r--r--source/blender/blenkernel/BKE_key.h69
-rw-r--r--source/blender/blenkernel/BKE_lattice.h59
-rw-r--r--source/blender/blenkernel/BKE_library.h69
-rw-r--r--source/blender/blenkernel/BKE_main.h80
-rw-r--r--source/blender/blenkernel/BKE_material.h68
-rw-r--r--source/blender/blenkernel/BKE_mball.h64
-rw-r--r--source/blender/blenkernel/BKE_mesh.h116
-rw-r--r--source/blender/blenkernel/BKE_nla.h46
-rw-r--r--source/blender/blenkernel/BKE_object.h99
-rw-r--r--source/blender/blenkernel/BKE_osa_types.h53
-rw-r--r--source/blender/blenkernel/BKE_packedFile.h61
-rw-r--r--source/blender/blenkernel/BKE_plugin_types.h70
-rw-r--r--source/blender/blenkernel/BKE_property.h54
-rw-r--r--source/blender/blenkernel/BKE_sca.h74
-rw-r--r--source/blender/blenkernel/BKE_scene.h56
-rw-r--r--source/blender/blenkernel/BKE_screen.h40
-rw-r--r--source/blender/blenkernel/BKE_sound.h51
-rw-r--r--source/blender/blenkernel/BKE_subsurf.h43
-rw-r--r--source/blender/blenkernel/BKE_text.h128
-rw-r--r--source/blender/blenkernel/BKE_texture.h85
-rw-r--r--source/blender/blenkernel/BKE_utildefines.h300
-rw-r--r--source/blender/blenkernel/BKE_world.h45
-rw-r--r--source/blender/blenkernel/BKE_writeavi.h50
-rw-r--r--source/blender/blenkernel/Makefile37
-rw-r--r--source/blender/blenkernel/bad_level_call_stubs/Makefile55
-rw-r--r--source/blender/blenkernel/bad_level_call_stubs/stubs.c180
-rw-r--r--source/blender/blenkernel/intern/Makefile74
-rw-r--r--source/blender/blenkernel/intern/action.c873
-rw-r--r--source/blender/blenkernel/intern/anim.c512
-rw-r--r--source/blender/blenkernel/intern/armature.c1451
-rw-r--r--source/blender/blenkernel/intern/blender.c343
-rw-r--r--source/blender/blenkernel/intern/bmfont.c293
-rw-r--r--source/blender/blenkernel/intern/constraint.c732
-rw-r--r--source/blender/blenkernel/intern/curve.c2344
-rw-r--r--source/blender/blenkernel/intern/deform.c120
-rw-r--r--source/blender/blenkernel/intern/displist.c2085
-rw-r--r--source/blender/blenkernel/intern/effect.c854
-rw-r--r--source/blender/blenkernel/intern/exotic.c4081
-rw-r--r--source/blender/blenkernel/intern/font.c656
-rw-r--r--source/blender/blenkernel/intern/group.c329
-rw-r--r--source/blender/blenkernel/intern/ika.c596
-rw-r--r--source/blender/blenkernel/intern/image.c1486
-rw-r--r--source/blender/blenkernel/intern/ipo.c1878
-rw-r--r--source/blender/blenkernel/intern/key.c1212
-rw-r--r--source/blender/blenkernel/intern/lattice.c633
-rw-r--r--source/blender/blenkernel/intern/library.c905
-rw-r--r--source/blender/blenkernel/intern/material.c747
-rw-r--r--source/blender/blenkernel/intern/mball.c1540
-rw-r--r--source/blender/blenkernel/intern/mesh.c1120
-rw-r--r--source/blender/blenkernel/intern/nla.c118
-rw-r--r--source/blender/blenkernel/intern/object.c1681
-rw-r--r--source/blender/blenkernel/intern/packedFile.c638
-rw-r--r--source/blender/blenkernel/intern/property.c269
-rw-r--r--source/blender/blenkernel/intern/sca.c631
-rw-r--r--source/blender/blenkernel/intern/scene.c536
-rw-r--r--source/blender/blenkernel/intern/screen.c53
-rw-r--r--source/blender/blenkernel/intern/sound.c112
-rw-r--r--source/blender/blenkernel/intern/subsurf.c890
-rw-r--r--source/blender/blenkernel/intern/text.c1986
-rw-r--r--source/blender/blenkernel/intern/texture.c2320
-rw-r--r--source/blender/blenkernel/intern/world.c201
-rw-r--r--source/blender/blenkernel/intern/writeavi.c147
84 files changed, 38547 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
new file mode 100644
index 00000000000..53fe4a7146c
--- /dev/null
+++ b/source/blender/blenkernel/BKE_action.h
@@ -0,0 +1,238 @@
+/* BKE_action.h May 2001
+ *
+ * Blender kernel action functionality
+ *
+ * Reevan McKay
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BKE_ACTION_H
+#define BKE_ACTION_H
+
+#include "DNA_listBase.h"
+
+/**
+ * The following structures are defined in DNA_action_types.h
+ */
+
+struct bAction;
+struct bActionChannel;
+struct bPose;
+struct bPoseChannel;
+struct Object;
+
+/* Kernel prototypes */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Allocate a new pose channel on the heap and binary copy the
+ * contents of the src pose channel.
+ */
+ struct bPoseChannel *
+copy_pose_channel (
+ const struct bPoseChannel *src
+);
+
+/**
+ * Removes and deallocates all channels from a pose.
+ * Does not free the pose itself.
+ */
+ void
+clear_pose (
+ struct bPose *pose
+);
+
+/* Sets the value of a pose channel */
+ struct bPoseChannel *
+set_pose_channel (
+ struct bPose *pose,
+ struct bPoseChannel *chan
+);
+
+/**
+ * Allocate a new pose on the heap, and copy the src pose and it's channels
+ * into the new pose. *dst is set to the newly allocated structure.
+ */
+ void
+copy_pose(
+ struct bPose **dst,
+ const struct bPose *src,
+ int copyconstraints
+);
+
+/**
+ * Deallocate the action's channels including constraint channels.
+ * does not free the action structure.
+ */
+ void
+free_action(
+ struct bAction * id
+);
+
+ void
+make_local_action(
+ struct bAction *act
+);
+
+ void
+do_all_actions(
+ void
+);
+
+/**
+ * Return a pointer to the pose channel of the given name
+ * from this pose.
+ */
+
+ struct bPoseChannel *
+get_pose_channel (
+ const struct bPose *pose,
+ const char *name
+);
+
+/**
+ * Looks to see if the channel with the given name
+ * already exists in this pose - if not a new one is
+ * allocated and initialized.
+ */
+ void
+verify_pose_channel (
+ struct bPose* pose,
+ const char* name
+);
+
+/**
+ * Allocate a new bAction on the heap and copy
+ * the contents of src into it. If src is NULL NULL is returned.
+ */
+
+ struct bAction*
+copy_action(
+ const struct bAction *src
+);
+
+/**
+ * Some kind of bounding box operation on the action.
+ */
+
+ float
+calc_action_start (
+ const struct bAction *act
+);
+
+ float
+calc_action_end (
+ const struct bAction *act
+);
+
+/**
+ * Evaluate the pose from the given action.
+ * If the pose does not exist, a new one is created.
+ * Some deep calls into blender are made here.
+ */
+ void
+get_pose_from_action (
+ struct bPose **pose,
+ struct bAction *act,
+ float ctime
+);
+
+/**
+ * I think this duplicates the src into *pose.
+ * If the pose does not exist, a new one is created.
+ * If the pose does not contain channels from src
+ * new channels are created.
+ */
+ void
+get_pose_from_pose (
+ struct bPose **pose,
+ const struct bPose *src
+);
+
+ void
+clear_pose_constraint_status (
+ struct Object *ob
+);
+
+/**
+ * Blends the common subset of channels from dst and src.
+ * and writes result to dst.
+ */
+ void
+blend_poses (
+ struct bPose *dst,
+ const struct bPose *src,
+ float srcweight,
+ short mode
+);
+
+/**
+ * Iterate through the action channels of the action
+ * and return the channel with the given name.
+ * Returns NULL if no channel.
+ */
+
+ struct bActionChannel *
+get_named_actionchannel (
+ struct bAction *act,
+ const char *name
+);
+
+#ifdef __cplusplus
+};
+#endif
+
+enum {
+ POSE_BLEND = 0,
+ POSE_ADD
+};
+
+enum {
+ POSE_KEY = 0x10000000,
+ POSE_LOC = 0x00000001,
+ POSE_ROT = 0x00000002,
+ POSE_SIZE = 0x00000004,
+ POSE_UNUSED1 = 0x00000008,
+ POSE_UNUSED2 = 0x00000010,
+ POSE_UNUSED3 = 0x00000020,
+ POSE_UNUSED4 = 0x00000040,
+ POSE_UNUSED5 = 0x00000080,
+ POSE_OBMAT = 0x00000100,
+ POSE_PARMAT = 0x00000200,
+ PCHAN_DONE = 0x00000400
+
+};
+#endif
+
+
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h
new file mode 100644
index 00000000000..93faf2d34bc
--- /dev/null
+++ b/source/blender/blenkernel/BKE_anim.h
@@ -0,0 +1,52 @@
+/**
+ * blenlib/BKE_anim.h (mar-2001 nzc);
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_ANIM_H
+#define BKE_ANIM_H
+
+struct Path;
+struct Object;
+struct PartEff;
+struct Scene;
+
+void free_path(struct Path *path);
+void calc_curvepath(struct Object *ob);
+int interval_test(int min, int max, int p1, int cycl);
+int where_on_path(struct Object *ob, float ctime, float *vec, float *dir);
+void frames_duplilist(struct Object *ob);
+void vertex_duplilist(struct Scene *sce, struct Object *par);
+void particle_duplilist(struct Scene *sce, struct Object *par, struct PartEff *paf);
+void free_duplilist(void);
+void make_duplilist(struct Scene *sce, struct Object *ob);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
new file mode 100644
index 00000000000..4e52d154644
--- /dev/null
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -0,0 +1,121 @@
+/**
+ * blenlib/BKE_armature.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_ARMATURE_H
+#define BKE_ARMATURE_H
+
+struct Bone;
+struct Main;
+struct bArmature;
+struct bPose;
+struct Object;
+struct MDeformVert;
+struct Mesh;
+struct PoseChain;
+struct ListBase;
+
+typedef struct PoseChain
+{
+ struct PoseChain *next, *prev;
+ struct Bone *root;
+ struct Bone *target;
+ struct bPose *pose;
+ float goal[3];
+ float tolerance;
+ int iterations;
+ float goalinv[4][4];
+ struct IK_Chain_Extern *solver;
+} PoseChain;
+
+/* Core armature functionality */
+#ifdef __cplusplus
+extern "C" {
+#endif
+struct bArmature *add_armature(void);
+void free_boneChildren(struct Bone *bone);
+void free_bones (struct bArmature *arm);
+void unlink_armature(struct bArmature *arm);
+void free_armature(struct bArmature *arm);
+void make_local_armature(struct bArmature *arm);
+struct bArmature *copy_armature(struct bArmature *arm);
+void apply_pose_armature (struct bArmature* arm, struct bPose* pose, int doit);
+void calc_armature_deform (struct Object *ob, float *co, int index);
+int verify_boneptr (struct bArmature *arm, struct Bone *tBone);
+void init_armature_deform(struct Object *parent, struct Object *ob);
+struct bArmature* get_armature (struct Object* ob);
+struct Bone *get_named_bone (struct bArmature *arm, const char *name);
+struct Bone *get_indexed_bone (struct bArmature *arm, int index);
+void make_displists_by_armature (struct Object *ob);
+void calc_bone_deform (struct Bone *bone, float weight, float *vec, float *co, float *contrib);
+
+void where_is_armature_time (struct Object *ob, float ctime);
+void where_is_armature (struct Object *ob);
+void where_is_bone1_time (struct Object *ob, struct Bone *bone, float ctime);
+
+/* Handy bone matrix functions */
+void bone_to_mat4(struct Bone *bone, float mat[][4]);
+void bone_to_mat3(struct Bone *bone, float mat[][3]);
+void make_boneMatrixvr (float outmatrix[][4],float delta[3], float roll);
+void make_boneMatrix (float outmatrix[][4], struct Bone *bone);
+void get_bone_root_pos (struct Bone* bone, float vec[3], int posed);
+void get_bone_tip_pos (struct Bone* bone, float vec[3], int posed);
+float get_bone_length (struct Bone *bone);
+void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed);
+void precalc_bone_irestmat (struct Bone *bone);
+void precalc_armature_posemats (struct bArmature *arm);
+void precalc_bonelist_irestmats (struct ListBase* bonelist);
+void apply_bonemat(struct Bone *bone);
+
+/* void make_armatureParentMatrices (struct bArmature *arm); */
+void precalc_bone_defmat (struct Bone *bone);
+void rebuild_bone_parent_matrix (struct Bone *bone);
+
+/* Animation functions */
+void where_is_bone_time (struct Object *ob, struct Bone *bone, float ctime);
+void where_is_bone (struct Object *ob, struct Bone *bone);
+struct PoseChain *ik_chain_to_posechain (struct Object *ob, struct Bone *bone);
+void solve_posechain (PoseChain *chain);
+void free_posechain (PoseChain *chain);
+
+/* Gameblender hacks */
+void GB_init_armature_deform(struct ListBase *defbase, float premat[][4], float postmat[][4]);
+void GB_calc_armature_deform (float *co, struct MDeformVert *dvert);
+void GB_build_mats (float parmat[][4], float obmat[][4], float premat[][4], float postmat[][4]);
+void GB_validate_defgroups (struct Mesh *mesh, struct ListBase *defbase);
+
+/*void make_boneParentMatrix (struct Bone* bone, float mat[][4]);*/
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h
new file mode 100644
index 00000000000..420a915adf6
--- /dev/null
+++ b/source/blender/blenkernel/BKE_bad_level_calls.h
@@ -0,0 +1,143 @@
+/**
+ * blenlib/BKE_bad_level_calls.h (mar-2001 nzc)
+ *
+ * Stuff that definitely does not belong in the kernel! These will all
+ * have to be removed in order to restore sanity.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_BAD_LEVEL_CALLS_H
+#define BKE_BAD_LEVEL_CALLS_H
+
+/* readfile.c */
+struct PluginSeq;
+void open_plugin_seq(struct PluginSeq *pis, char *seqname);
+struct SpaceButs;
+void set_rects_butspace(struct SpaceButs *buts);
+struct SpaceImaSel;
+void check_imasel_copy(struct SpaceImaSel *simasel);
+struct ScrArea;
+struct bScreen;
+void unlink_screen(struct bScreen *sc);
+void freeAllRad(void);
+void free_editText(void);
+void setscreen(struct bScreen *sc);
+void force_draw_all(void);
+ /* otherwise the WHILE_SEQ doesn't work */
+struct Sequence;
+void build_seqar(struct ListBase *seqbase, struct Sequence ***seqar, int *totseq);
+
+struct ID;
+void BPY_do_pyscript (struct ID *id, short int event);
+
+/* writefile.c */
+struct Oops;
+void free_oops(struct Oops *oops);
+void error(char *str, ...);
+
+/* anim.c */
+extern struct ListBase editNurb;
+
+/* displist.c */
+#include "DNA_world_types.h" /* for render_types */
+#include "render_types.h"
+extern struct RE_Render R;
+float RE_Spec(float, int);
+void waitcursor(int);
+void allqueue(unsigned short event, short val);
+#define REDRAWVIEW3D 0x4010
+struct Material;
+extern struct Material defmaterial;
+
+/* effect.c */
+void RE_jitterate1(float *jit1, float *jit2, int num, float rad1);
+void RE_jitterate2(float *jit1, float *jit2, int num, float rad2);
+
+/* exotic.c */
+void load_editMesh(void);
+void make_editMesh(void);
+void free_editMesh(void);
+void free_editArmature(void);
+void docentre_new(void);
+int saveover(char *str);
+
+/* image.c */
+#include "DNA_image_types.h"
+void free_realtime_image(Image *ima); // has to become a callback, opengl stuff
+void RE_make_existing_file(char *name); // from render, but these funcs should be moved anyway
+
+/* ipo.c */
+void copy_view3d_lock(short val); // was a hack, to make scene layer ipo's possible
+
+/* library.c */
+void allspace(unsigned short event, short val) ;
+#define OOPS_TEST 2
+
+/* mball.c */
+extern ListBase editelems;
+
+/* object.c */
+/* void BPY_free_scriptlink(ScriptLink *slink); */
+/* void BPY_copy_scriptlink(ScriptLink *scriptlink); */
+float *give_cursor(void); // become a callback or argument
+void exit_posemode(int freedata);
+
+/* packedFile.c */
+short pupmenu(char *instr); // will be general callback
+
+/* sca.c */
+#define LEFTMOUSE 0x001 // because of mouse sensor
+
+/* scene.c */
+#include "DNA_sequence_types.h"
+void free_editing(struct Editing *ed); // scenes and sequences problem...
+
+/* texture.c */
+#define FLO 128
+#define INT 96
+struct EnvMap;
+struct Tex;
+void RE_free_envmap(struct EnvMap *env);
+struct EnvMap *RE_copy_envmap(struct EnvMap *env);
+void RE_free_envmapdata(struct EnvMap *env);
+int RE_envmaptex(struct Tex *tex, float *texvec, float *dxt, float *dyt);
+void RE_calc_R_ref(void);
+extern char texstr[15][8]; /* buttons.c */
+
+/* memory for O is declared in the render module... */
+#include "BKE_osa_types.h"
+extern Osa O;
+
+/* editsca.c */
+void make_unique_prop_names(char *str);
+
+#endif
+
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
new file mode 100644
index 00000000000..db38a85bfcd
--- /dev/null
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -0,0 +1,64 @@
+/**
+ * blenlib/BKE_blender.h (mar-2001 nzc)
+ *
+ * Blender util stuff?
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_BLENDER_H
+#define BKE_BLENDER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ListBase;
+
+#define BLENDER_VERSION 225
+
+int BKE_read_file(char *dir, void *type_r);
+int BKE_read_file_from_memory(char* filebuf, int filelength, void *type_r);
+
+void duplicatelist(struct ListBase *list1, struct ListBase *list2);
+void free_blender(void);
+void initglobals(void);
+
+void pushdata(void *data, int len);
+void popfirst(void *data);
+void poplast(void *data);
+void free_pushpop(void);
+void pushpop_test(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_bmfont.h b/source/blender/blenkernel/BKE_bmfont.h
new file mode 100644
index 00000000000..5fc9045d05e
--- /dev/null
+++ b/source/blender/blenkernel/BKE_bmfont.h
@@ -0,0 +1,64 @@
+/**
+ * blenlib/BKE_bmfont.h (mar-2001 nzc)
+ *
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_BMFONT_H
+#define BKE_BMFONT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bmGlyph;
+struct ImBuf;
+struct bmFont;
+
+void printfGlyph(struct bmGlyph * glyph);
+void calcAlpha(struct ImBuf * ibuf);
+void readBitmapFontVersion0(struct ImBuf * ibuf,
+ unsigned char * rect,
+ int step);
+void detectBitmapFont(struct ImBuf *ibuf);
+int locateGlyph(struct bmFont *bmfont, unsigned short unicode);
+void matrixGlyph(struct ImBuf * ibuf, unsigned short unicode,
+ float *centerx, float *centery,
+ float *sizex, float *sizey,
+ float *transx, float *transy,
+ float *movex, float *movey, float *advance);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_bmfont_types.h b/source/blender/blenkernel/BKE_bmfont_types.h
new file mode 100644
index 00000000000..84fa16779dd
--- /dev/null
+++ b/source/blender/blenkernel/BKE_bmfont_types.h
@@ -0,0 +1,61 @@
+/**
+ * blenlib/BKE_bmfont_types.h (mar-2001 nzc)
+ *
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_BMFONT_TYPES_H
+#define BKE_BMFONT_TYPES_H
+
+#define is_power_of_two(N) ((N ^ (N - 1)) == (2 * N - 1))
+/*
+Moved to IMB_imbuf_types.h where it will live close to the ImBuf type.
+It is used as a userflag bit mask.
+#define IB_BITMAPFONT 1
+*/
+typedef struct bmGlyph {
+ unsigned short unicode;
+ short locx, locy;
+ signed char ofsx, ofsy;
+ unsigned char sizex, sizey;
+ unsigned char advance, reserved;
+} bmGlyph;
+
+typedef struct bmFont {
+ char magic[4];
+ short version;
+ short glyphcount;
+ short xsize, ysize;
+ bmGlyph glyphs[1];
+} bmFont;
+
+#endif
diff --git a/source/blender/blenkernel/BKE_booleanops.h b/source/blender/blenkernel/BKE_booleanops.h
new file mode 100644
index 00000000000..df1906a2c70
--- /dev/null
+++ b/source/blender/blenkernel/BKE_booleanops.h
@@ -0,0 +1,143 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_BOOLEANOPS_H
+#define BKE_BOOLEANOPS_H
+
+
+struct Mesh;
+struct Object;
+struct Base;
+struct CSG_FaceIteratorDescriptor;
+struct CSG_VertexIteratorDescriptor;
+struct CSG_MeshPropertyDescriptor;
+
+/**
+ * Perform a boolean operation between 2 mesh objects and
+ * add the result as a new mesh into blender data structures.
+ * Assumes you have checked that the 2 objects are infact mesh
+ * objects. Returns 1 on success and zero when it encountered
+ * a problem. In the latter case no object is added and you should
+ * report an appropriate error.
+ */
+extern
+ int
+NewBooleanMesh(
+ struct Base * base,
+ struct Base * base_select,
+ int op_type
+);
+
+
+/**
+ * Functions exposed for use by BKE_booleanops_mesh
+ */
+
+/**
+ * Returns pointers to new mesh descriptors for
+ * the given mesh. Make sure you call FreeMeshDescriptors
+ * after calling this function.
+ */
+
+extern
+ void
+BuildMeshDescriptors(
+ struct Object * ob,
+ struct CSG_FaceIteratorDescriptor * face_it,
+ struct CSG_VertexIteratorDescriptor * vertex_it
+);
+
+extern
+ void
+FreeMeshDescriptors(
+ struct CSG_FaceIteratorDescriptor * face_it,
+ struct CSG_VertexIteratorDescriptor * vertex_it
+);
+
+extern
+ int
+ConvertCSGDescriptorsToMeshObject(
+ struct Object *ob,
+ struct CSG_MeshPropertyDescriptor * props,
+ struct CSG_FaceIteratorDescriptor * face_it,
+ struct CSG_VertexIteratorDescriptor * vertex_it,
+ float parinv[][4]
+);
+
+/**
+ * This little function adds a new mesh object
+ * to the blender object list. It uses ob to duplicate
+ * data as this seems to be easier than cerating a new one.
+ * This new oject contains no faces nor vertices.
+ */
+
+extern
+ struct Object *
+AddNewBlenderMesh(
+ struct Base *base
+);
+
+extern
+ int
+InterpNoUserData(
+ void *d1,
+ void *d2,
+ void *dnew,
+ float epsilon
+);
+
+extern
+ int
+InterpFaceVertexData(
+ void *d1,
+ void *d2,
+ void *dnew,
+ float epsilon
+);
+
+typedef struct {
+ float uv[2];
+ float color[4];
+} FaceVertexData;
+
+typedef struct {
+ struct Material *material;
+
+ /* assorted tface flags */
+ void *tpage;
+ char flag, transp;
+ short mode, tile;
+} FaceData;
+
+
+
+
+#endif
diff --git a/source/blender/blenkernel/BKE_booleanops_mesh.h b/source/blender/blenkernel/BKE_booleanops_mesh.h
new file mode 100644
index 00000000000..9a92df9e3b1
--- /dev/null
+++ b/source/blender/blenkernel/BKE_booleanops_mesh.h
@@ -0,0 +1,122 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_PyBooleanOps_h
+#define BKE_PyBooleanOps_h
+
+#include "CSG_BooleanOps.h"
+
+/**
+ * Internal mesh structure.
+ * Safe to copy by value... hopefully.
+ */
+
+struct Base;
+struct Object;
+struct CSG_MeshDescriptor;
+
+typedef void (*CSG_DestroyMeshFunc)(struct CSG_MeshDescriptor *);
+
+typedef struct CSG_MeshDescriptor {
+ struct Base *base; // Ptr to base of original blender object - used in creating a new object
+ CSG_MeshPropertyDescriptor m_descriptor;
+ CSG_FaceIteratorDescriptor m_face_iterator;
+ CSG_VertexIteratorDescriptor m_vertex_iterator;
+ CSG_DestroyMeshFunc m_destroy_func;
+} CSG_MeshDescriptor;
+
+
+extern
+ int
+CSG_LoadBlenderMesh(
+ struct Object * obj,
+ CSG_MeshDescriptor *output
+);
+
+/**
+ * Destroy the contents of a mesh descriptor.
+ * If the internal descriptor refers to a blender
+ * mesh, no action is performed apart from freeing
+ * internal memory in the desriptor.
+ */
+
+extern
+ void
+CSG_DestroyMeshDescriptor(
+ CSG_MeshDescriptor *mesh
+);
+
+/**
+ * Perform a boolean operation between 2 meshes and return the
+ * result as a new mesh descriptor.
+ * op_type is an integer code of the boolean operation type.
+ * 1 = intersection,
+ * 2 = union,
+ * 3 = difference.
+ */
+
+extern
+ int
+CSG_PerformOp(
+ CSG_MeshDescriptor *mesh1,
+ CSG_MeshDescriptor *mesh2,
+ int op_type,
+ CSG_MeshDescriptor *output
+);
+
+
+
+/**
+ * Add a mesh to blender as a new object.
+ */
+
+extern
+ int
+CSG_AddMeshToBlender(
+ CSG_MeshDescriptor *mesh
+);
+
+/**
+ * Test functionality.
+ */
+
+extern
+ int
+NewBooleanMeshTest(
+ struct Base * base,
+ struct Base * base_select,
+ int op_type
+);
+
+
+
+
+#endif
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
new file mode 100644
index 00000000000..2cc323c14ff
--- /dev/null
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -0,0 +1,64 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BKE_CONSTRAINT_H
+#define BKE_CONSTRAINT_H
+
+struct bConstraint;
+struct Object;
+struct ListBase;
+struct bConstraintChannel;
+struct bAction;
+struct bArmature;
+
+/* Function prototypes */
+void evaluate_constraint (struct bConstraint *constraint, struct Object *ob, short ownertype, void *ownerdata, float targetmat[][4]);
+void free_constraints (struct ListBase *conlist);
+void copy_constraints (struct ListBase *dst, struct ListBase *src);
+void *copy_constraint_channels (ListBase *dst, ListBase *src);
+struct bConstraintChannel *clone_constraint_channels (struct ListBase *dst, struct ListBase *src, struct bConstraintChannel *oldact);
+void relink_constraints (struct ListBase *list);
+void free_constraint_data (struct bConstraint *con);
+void clear_object_constraint_status (struct Object *ob);
+void do_constraint_channels (struct ListBase *conbase, struct ListBase *chanbase, float ctime);
+short get_constraint_target (struct bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float size[3], float time);
+struct bConstraintChannel *find_constraint_channel (ListBase *list, const char *name);
+void free_constraint_channels (ListBase *chanbase);
+
+/* Constraint target/owner types */
+#define TARGET_OBJECT 1 // string is ""
+#define TARGET_BONE 2 // string is bone-name
+#define TARGET_VERT 3 // string is "VE:#"
+#define TARGET_FACE 4 // string is "FA:#"
+#define TARGET_CV 5 // string is "CV:#"
+
+#endif
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
new file mode 100644
index 00000000000..7325594394a
--- /dev/null
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -0,0 +1,86 @@
+/**
+ * blenlib/BKE_curve.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_CURVE_H
+#define BKE_CURVE_H
+
+struct Curve;
+struct ListBase;
+struct Object;
+struct Nurb;
+struct ListBase;
+struct BezTriple;
+struct BevList;
+
+
+int copyintoExtendedArray(float *old, int oldx, int oldy, float *newp, int newx, int newy);
+void unlink_curve( struct Curve *cu);
+void free_curve( struct Curve *cu);
+struct Curve *add_curve(int type);
+struct Curve *copy_curve( struct Curve *cu);
+void make_local_curve( struct Curve *cu);
+void test_curve_type( struct Object *ob);
+void tex_space_curve( struct Curve *cu);
+int count_curveverts( struct ListBase *nurb);
+void freeNurb( struct Nurb *nu);
+void freeNurblist( struct ListBase *lb);
+struct Nurb *duplicateNurb( struct Nurb *nu);
+void duplicateNurblist( struct ListBase *lb1, struct ListBase *lb2);
+void test2DNurb( struct Nurb *nu);
+void minmaxNurb( struct Nurb *nu, float *min, float *max);
+void extend_spline(float * pnts, int in, int out);
+void calcknots(float *knots, short aantal, short order, short type);
+void makecyclicknots(float *knots, short pnts, short order);
+void makeknots( struct Nurb *nu, short uv, short type);
+void basisNurb(float t, short order, short pnts, float *knots, float *basis, int *start, int *end);
+void makeNurbfaces( struct Nurb *nu, float *data);
+void makeNurbcurve_forw(struct Nurb *nu, float *data);
+void makeNurbcurve( struct Nurb *nu, float *data, int dim);
+void maakbez(float q0, float q1, float q2, float q3, float *p, int it);
+void make_orco_surf( struct Curve *cu);
+void makebevelcurve( struct Object *ob, struct ListBase *disp);
+short bevelinside(struct BevList *bl1,struct BevList *bl2);
+int vergxcobev(const void *a1, const void *a2);
+void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *sina, float *cosa);
+void alfa_bezpart( struct BezTriple *prevbezt, struct BezTriple *bezt, struct Nurb *nu, float *data_a);
+void makeBevelList( struct Object *ob);
+void calchandleNurb( struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next, int mode);
+void calchandlesNurb( struct Nurb *nu);
+void testhandlesNurb( struct Nurb *nu);
+void autocalchandlesNurb( struct Nurb *nu, int flag);
+void autocalchandlesNurb_all(int flag);
+void sethandlesNurb(short code);
+void swapdata(void *adr1, void *adr2, int len);
+void switchdirectionNurb( struct Nurb *nu);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h
new file mode 100644
index 00000000000..e7494f28fc4
--- /dev/null
+++ b/source/blender/blenkernel/BKE_deform.h
@@ -0,0 +1,50 @@
+/* BKE_deform.h June 2001
+ *
+ * support for deformation groups
+ *
+ * Reevan McKay
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BKE_DEFORM_H
+#define BKE_DEFORM_H
+
+struct Object;
+struct ListBase;
+struct bDeformGroup;
+
+void copy_defgroups (struct ListBase *lb1, struct ListBase *lb2);
+struct bDeformGroup* copy_defgroup (struct bDeformGroup *ingroup);
+void color_temperature (float input, unsigned char *r, unsigned char *g, unsigned char *b);
+
+#endif
+
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
new file mode 100644
index 00000000000..8942a6712d6
--- /dev/null
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -0,0 +1,117 @@
+/* display list (or rather multi purpose list) stuff */
+/*
+ $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+*/
+
+#ifndef BKE_DISPLIST_H
+#define BKE_DISPLIST_H
+
+
+#define DL_POLY 0
+#define DL_SEGM 1
+#define DL_SURF 2
+#define DL_TRIA 3
+#define DL_INDEX3 4
+#define DL_INDEX4 5
+#define DL_VERTCOL 6
+#define DL_VERTS 7
+#define DL_NORS 8
+#define DL_MESH 9
+
+/* EVIL: #define DL_SURFINDEX(cyclu, cyclv, sizeu, sizev) */
+
+/* prototypes */
+
+struct Object;
+struct Curve;
+struct ListBase;
+struct Material;
+struct Bone;
+struct TFace;
+
+typedef struct DispListMesh DispListMesh;
+struct DispListMesh {
+ int totvert, totface;
+ struct MVert *mvert;
+ struct MCol *mcol;
+ struct MFaceInt *mface;
+ struct TFace *tface;
+};
+
+/*
+ * All the different DispList.type's use the
+ * data in the displist structure in fairly
+ * different ways which can be rather confusing,
+ * the best thing to do would be to make a structure
+ * for each displaylist type that has the fields
+ * needed w/ proper names, and then make the actual
+ * DispList structure a typed union.
+ * - zr
+ */
+
+/* needs splitting! */
+typedef struct DispList {
+ struct DispList *next, *prev;
+ short type, flag;
+ int parts, nr;
+ short col, rt; /* rt wordt gebruikt door initrenderNurbs */
+ float *verts, *nors;
+ int *index;
+ unsigned int *col1, *col2;
+ struct DispListMesh *mesh;
+
+ /* Begin NASTY_NLA_STUFF */
+// int *offset, *run; /* Used to index into the bone & weight lists */
+// struct Bone *bones;
+// float *weights;
+ /* End NASTY_NLA_STUFF */
+} DispList;
+
+extern void copy_displist(struct ListBase *lbn, struct ListBase *lb);
+extern void free_disp_elem(DispList *dl);
+extern void free_displist_by_type(struct ListBase *lb, int type);
+extern DispList *find_displist_create(struct ListBase *lb, int type);
+extern DispList *find_displist(struct ListBase *lb, int type);
+extern void addnormalsDispList(struct Object *ob, struct ListBase *lb);
+extern void count_displist(struct ListBase *lb, int *totvert, int *totface);
+extern void curve_to_filledpoly(struct Curve *cu, struct ListBase *dispbase);
+extern void freedisplist(struct ListBase *lb);
+extern void makeDispList(struct Object *ob);
+extern void set_displist_onlyzero(int val);
+extern void shadeDispList(struct Object *ob);
+void freefastshade(void);
+void boundbox_displist(struct Object *ob);
+void imagestodisplist(void);
+void reshadeall_displist(void);
+void test_all_displists(void);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h
new file mode 100644
index 00000000000..23d504d0607
--- /dev/null
+++ b/source/blender/blenkernel/BKE_effect.h
@@ -0,0 +1,65 @@
+/**
+ * blenlib/BKE_effect.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_EFFECT_H
+#define BKE_EFFECT_H
+
+struct Effect;
+struct ListBase;
+struct Object;
+struct PartEff;
+struct MTex;
+struct Mesh;
+struct WaveEff;
+struct Particle;
+
+struct Effect *add_effect(int type);
+void free_effect(struct Effect *eff);
+void free_effects(struct ListBase *lb);
+struct Effect *copy_effect(struct Effect *eff);
+void copy_act_effect(struct Object *ob);
+void copy_effects(struct ListBase *lbn, struct ListBase *lb);
+void deselectall_eff(struct Object *ob);
+void set_buildvars(struct Object *ob, int *start, int *end);
+struct Particle *new_particle(struct PartEff *paf);
+struct PartEff *give_parteff(struct Object *ob);
+void where_is_particle(struct PartEff *paf, struct Particle *pa, float ctime, float *vec);
+void particle_tex(struct MTex *mtex, struct PartEff *paf, float *co, float *no);
+void make_particle_keys(int depth, int nr, struct PartEff *paf, struct Particle *part, float *force, int deform, struct MTex *mtex);
+void init_mv_jit(float *jit, int num);
+void give_mesh_mvert(struct Mesh *me, int nr, float *co, short *no);
+void build_particle_system(struct Object *ob);
+void calc_wave_deform(struct WaveEff *wav, float ctime, float *co);
+void object_wave(struct Object *ob);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_endian.h b/source/blender/blenkernel/BKE_endian.h
new file mode 100644
index 00000000000..a675ad893c4
--- /dev/null
+++ b/source/blender/blenkernel/BKE_endian.h
@@ -0,0 +1,46 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Are we little or big endian? From Harbison&Steele.
+ * BKE_ENDIANNESS(a) returns 1 if big endian and returns 0 if little endian
+ */
+#ifndef BKE_ENDIAN_H
+#define BKE_ENDIAN_H
+
+#define BKE_ENDIANNESS(a) { \
+ union { \
+ long l; \
+ char c[sizeof (long)]; \
+ } u; \
+ u.l = 1; \
+ a = (u.c[sizeof (long) - 1] == 1) ? 1 : 0; \
+}
+
+#endif
diff --git a/source/blender/blenkernel/BKE_exotic.h b/source/blender/blenkernel/BKE_exotic.h
new file mode 100644
index 00000000000..7223abb11ab
--- /dev/null
+++ b/source/blender/blenkernel/BKE_exotic.h
@@ -0,0 +1,54 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * dxf/vrml/videoscape external file io function prototypes
+ */
+
+#ifndef BKE_EXOTIC_H
+#define BKE_EXOTIC_H
+
+struct Mesh;
+
+void mcol_to_rgba(unsigned int col, float *r, float *g, float *b, float *a);
+unsigned int *mcol_to_vcol(struct Mesh *me); // used in py_main.c
+
+/**
+ * Reads all 3D fileformats other than Blender fileformat
+ * @retval 0 The file could not be read.
+ * @retval 1 The file was read succesfully.
+ * @attention Used in filesel.c
+ */
+int BKE_read_exotic(char *name);
+
+void write_dxf(char *str);
+void write_vrml(char *str);
+void write_videoscape(char *str);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h
new file mode 100644
index 00000000000..51968182663
--- /dev/null
+++ b/source/blender/blenkernel/BKE_font.h
@@ -0,0 +1,50 @@
+/**
+ * blenlib/BKE_vfont.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_VFONT_H
+#define BKE_VFONT_H
+
+struct VFont;
+struct Object;
+struct Curve;
+struct objfnt;
+
+void BKE_font_register_builtin(void *mem, int size);
+
+void free_vfont(struct VFont *sc);
+struct VFont *load_vfont(char *name);
+
+struct chartrans *text_to_curve(struct Object *ob, int mode);
+void font_duplilist(struct Object *par);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
new file mode 100644
index 00000000000..53c71f03606
--- /dev/null
+++ b/source/blender/blenkernel/BKE_global.h
@@ -0,0 +1,224 @@
+/**
+ * blenlib/BKE_global.h (mar-2001 nzc)
+ *
+ * Global settings, handles, pointers. This is the root for finding
+ * any data in Blender. This block is not serialized, but built anew
+ * for every fresh Blender run.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_GLOBAL_H
+#define BKE_GLOBAL_H
+
+#include "DNA_listBase.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* forwards */
+struct View3D;
+struct View2D;
+struct SpaceIpo;
+struct SpaceButs;
+struct SpaceImage;
+struct SpaceOops;
+struct SpaceText;
+struct SpaceSound;
+struct SpaceAction;
+struct SpaceNla;
+struct Main;
+struct Scene;
+struct bScreen;
+struct Object;
+struct bSoundListener;
+struct BMF_Font;
+
+typedef struct Global {
+
+ /* active pointers */
+ struct View3D *vd;
+ struct View2D *v2d;
+ struct SpaceIpo *sipo;
+ struct SpaceButs *buts;
+ struct SpaceImage *sima;
+ struct SpaceOops *soops;
+ struct SpaceSound *ssound;
+ struct SpaceAction *saction; /* __NLA */
+ struct SpaceNla *snla;
+ struct Main *main;
+ struct Scene *scene; /* denk aan file.c */
+ struct bScreen *curscreen;
+ struct Object *obedit;
+
+ /* fonts, allocated global data */
+ struct BMF_Font *font, *fonts, *fontss;
+
+ /* strings: lastsaved */
+ char ima[160], sce[160], lib[160];
+
+ /* totalen */
+ short totobj, totlamp, totobjsel, totcurve, totmesh, totmat;
+ int totvert, totface, totvertsel, totfacesel;
+
+ short machine, afbreek, moving, colact, zbuf;
+ short qual, background, imagewin, animspeed;
+ /**
+ * The current version of Blender.
+ */
+ short version;
+ short simulf, fields, order, rt;
+ int f;
+
+ /* Editmode lists */
+ struct ListBase edve;
+ struct ListBase eded;
+ struct ListBase edvl;
+
+ float textcurs[4][2];
+
+ /* Frank's variables */
+ int renderd;
+ int real_sfra, real_efra;
+ int save_over;
+
+ /* Reevan's __NLA variables */
+ struct Object *obpose; /* Current posable object */
+ struct ListBase edbo; /* Armature Editmode bones */
+
+ /* this variable is written to / read from FileGlobal->fileflags */
+ int fileflags;
+
+ /* Janco's playing ground */
+ struct bSoundListener* listener;
+
+ /* Test thingy for Nzc */
+ int magic; /* toggle use of experimental render pipe */
+ int compat; /* toggle compatibility mode for edge rendering */
+ int notonlysolid;/* T-> also edge-render transparent faces */
+ int useRscale; /* bitflag for using colour scaling */
+ int useGscale; /* bitflag for using colour scaling */
+ int useBscale; /* bitflag for using colour scaling */
+ float cscale[4]; /* sliders for colour scaling */
+ int Rhisto; /* flags for making histograms */
+ int Ghisto;
+ int Bhisto;
+
+ /* special versions */
+ short special1, special2;
+
+ int flags;
+
+} Global;
+
+/* **************** GLOBAL ********************* */
+
+/* G.f */
+#define G_DISABLE_OK 1
+#define G_PLAYANIM 2
+#define G_TEST_DUPLI 4
+#define G_SIMULATION 8
+#define G_BACKBUFSEL 16
+#define G_PICKSEL 32
+#define G_DRAWNORMALS 64
+#define G_DRAWFACES 128
+#define G_FACESELECT 256
+#define G_DRAW_EXT 512
+#define G_VERTEXPAINT 1024
+#define G_ALLEDGES 2048
+#define G_DEBUG 4096
+#define G_SCENESCRIPT 8192
+#define G_PROPORTIONAL 16384
+#define G_WEIGHTPAINT 32768 /* __NLA */
+#define G_TEXTUREPAINT 65536
+#define G_NOFROZEN (1 << 17) // frozen modules inactive
+
+/* G.fileflags */
+
+#define G_AUTOPACK_BIT 0
+#define G_FILE_COMPRESS_BIT 1
+#define G_FILE_AUTOPLAY_BIT 2
+#define G_FILE_ENABLE_ALL_FRAMES_BIT 3
+#define G_FILE_SHOW_DEBUG_PROPS_BIT 4
+#define G_FILE_SHOW_FRAMERATE_BIT 5
+#define G_FILE_SHOW_PROFILE_BIT 6
+#define G_FILE_LOCK_BIT 7
+#define G_FILE_SIGN_BIT 8
+#define G_FILE_PUBLISH_BIT 9
+
+#define G_AUTOPACK (1 << G_AUTOPACK_BIT)
+#define G_FILE_COMPRESS (1 << G_FILE_COMPRESS_BIT)
+#define G_FILE_AUTOPLAY (1 << G_FILE_AUTOPLAY_BIT)
+#define G_FILE_ENABLE_ALL_FRAMES (1 << G_FILE_ENABLE_ALL_FRAMES_BIT)
+#define G_FILE_SHOW_DEBUG_PROPS (1 << G_FILE_SHOW_DEBUG_PROPS_BIT)
+#define G_FILE_SHOW_FRAMERATE (1 << G_FILE_SHOW_FRAMERATE_BIT)
+#define G_FILE_SHOW_PROFILE (1 << G_FILE_SHOW_PROFILE_BIT)
+#define G_FILE_LOCK (1 << G_FILE_LOCK_BIT)
+#define G_FILE_SIGN (1 << G_FILE_SIGN_BIT)
+#define G_FILE_PUBLISH (1 << G_FILE_PUBLISH_BIT)
+
+/* G.simulf */
+#define G_LOADFILE 2
+#define G_RESTART 4
+#define G_QUIT 8
+#define G_SETSCENE 16
+
+/* G.flags: double? */
+#define G_FLAGS_AUTOPLAY_BIT 2
+#define G_FLAGS_AUTOPLAY (1 << G_FLAGS_AUTOPLAY_BIT)
+
+/* G.qual */
+#define R_SHIFTKEY 1
+#define L_SHIFTKEY 2
+#define LR_SHIFTKEY 3
+#define R_ALTKEY 4
+#define L_ALTKEY 8
+#define LR_ALTKEY 12
+#define R_CTRLKEY 16
+#define L_CTRLKEY 32
+#define LR_CTRLKEY 48
+
+/* G.order: indicates what endianness the platform where the file was
+ * written had. */
+#define L_ENDIAN 1
+#define B_ENDIAN 0
+
+/* G.special1 */
+#define G_HOLO 1
+
+/* Memory is allocated where? blender.c */
+extern Global G;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
new file mode 100644
index 00000000000..ef000e2c370
--- /dev/null
+++ b/source/blender/blenkernel/BKE_group.h
@@ -0,0 +1,58 @@
+/**
+ * blenlib/BKE_group.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_GROUP_H
+#define BKE_GROUP_H
+struct Group;
+struct GroupKey;
+struct GroupObject;
+struct ObjectKey;
+struct Object;
+
+void free_object_key(struct ObjectKey *ok);
+void free_group_object(struct GroupObject *go);
+void free_group(struct Group *group);
+struct Group *add_group(void);
+void object_to_obkey(struct Object *ob, struct ObjectKey *ok);
+void obkey_to_object(struct ObjectKey *ok, struct Object *ob);
+void add_object_key(struct GroupObject *go, struct GroupKey *gk);
+void add_to_group(struct Group *group, struct Object *ob);
+void rem_from_group(struct Group *group, struct Object *ob);
+void add_group_key(struct Group *group);
+void set_object_key(struct Object *ob, struct ObjectKey *ok);
+void set_group_key(struct Group *group);
+struct Group *find_group(struct Object *ob);
+void set_group_key_name(struct Group *group, char *name);
+void set_group_key_frame(struct Group *group, float frame);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_ika.h b/source/blender/blenkernel/BKE_ika.h
new file mode 100644
index 00000000000..053414d9359
--- /dev/null
+++ b/source/blender/blenkernel/BKE_ika.h
@@ -0,0 +1,59 @@
+/**
+ * blenlib/BKE_ika.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_IKA_H
+#define BKE_IKA_H
+
+struct Ika;
+struct Limb;
+struct Object;
+
+void unlink_ika(struct Ika *ika);
+void free_ika(struct Ika *ika);
+struct Ika *add_ika(void);
+struct Ika *copy_ika(struct Ika *ika);
+void make_local_ika(struct Ika *ika);
+int count_limbs(struct Object *ob);
+void calc_limb(struct Limb *li);
+void calc_ika(struct Ika *ika, struct Limb *li);
+void init_defstate_ika(struct Object *ob);
+void itterate_limb(struct Ika *ika, struct Limb *li);
+void rotate_ika(struct Object *ob, struct Ika *ika);
+void rotate_ika_xy(struct Object *ob, struct Ika *ika);
+void itterate_ika(struct Object *ob);
+void do_all_ikas(void);
+void do_all_visible_ikas(void);
+void init_skel_deform(struct Object *par, struct Object *ob);
+void calc_skel_deform(struct Ika *ika, float *co);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
new file mode 100644
index 00000000000..4783b66706a
--- /dev/null
+++ b/source/blender/blenkernel/BKE_image.h
@@ -0,0 +1,67 @@
+/**
+ * blenlib/BKE_image.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_IMAGE_H
+#define BKE_IMAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Image;
+struct ImBuf;
+struct Tex;
+struct anim;
+
+void free_image(struct Image *me);
+void free_image_buffers(struct Image *ima);
+struct Image *add_image(char *name);
+void free_unused_animimages(void);
+void makepicstring(char *string, int frame);
+struct anim *openanim(char * name, int flags);
+int calcimanr(int cfra, struct Tex *tex);
+void do_laseroptics_patch(struct ImBuf *ibuf);
+void de_interlace_ng(struct ImBuf *ibuf);
+void de_interlace_st(struct ImBuf *ibuf);
+void load_image(struct Image * ima, int flags, char *relabase, int framenum);
+void ima_ibuf_is_nul(struct Tex *tex);
+int imagewrap(struct Tex *tex, float *texvec);
+int imagewraposa(struct Tex *tex, float *texvec, float *dxt, float *dyt);
+void converttopremul(struct ImBuf *ibuf);
+void makemipmap(struct Image *ima);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_ipo.h b/source/blender/blenkernel/BKE_ipo.h
new file mode 100644
index 00000000000..4a68884d53c
--- /dev/null
+++ b/source/blender/blenkernel/BKE_ipo.h
@@ -0,0 +1,101 @@
+/**
+ * blenlib/BKE_ipo.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_IPO_H
+#define BKE_IPO_H
+
+typedef struct CfraElem {
+ struct CfraElem *next, *prev;
+ float cfra;
+ int sel;
+} CfraElem;
+
+struct Ipo;
+struct IpoCurve;
+struct MTex;
+struct Material;
+struct Object;
+struct Sequence;
+struct ListBase;
+struct BezTriple;
+/* struct IPO_Channel; */
+
+float frame_to_float(int cfra);
+void free_ipo(struct Ipo *ipo);
+struct Ipo *add_ipo(char *name, int idcode);
+struct Ipo *copy_ipo(struct Ipo *ipo);
+void make_local_obipo(struct Ipo *ipo);
+void make_local_matipo(struct Ipo *ipo);
+void make_local_keyipo(struct Ipo *ipo);
+void make_local_ipo(struct Ipo *ipo);
+void calchandles_ipocurve(struct IpoCurve *icu);
+void testhandles_ipocurve(struct IpoCurve *icu);
+void sort_time_ipocurve(struct IpoCurve *icu);
+int test_time_ipocurve(struct IpoCurve *icu);
+void correct_bezpart(float *v1, float *v2, float *v3, float *v4);
+int findzero(float x, float q0, float q1, float q2, float q3, float *o);
+void berekeny(float f1, float f2, float f3, float f4, float *o, int b);
+void berekenx(float *f, float *o, int b);
+float eval_icu(struct IpoCurve *icu, float ipotime);
+void calc_icu(struct IpoCurve *icu, float ctime);
+float calc_ipo_time(struct Ipo *ipo, float ctime);
+void calc_ipo(struct Ipo *ipo, float ctime);
+void write_ipo_poin(void *poin, int type, float val);
+float read_ipo_poin(void *poin, int type);
+void *give_mtex_poin(struct MTex *mtex, int adrcode );
+void *get_ipo_poin(struct ID *id, struct IpoCurve *icu, int *type);
+void set_icu_vars(struct IpoCurve *icu);
+void execute_ipo(struct ID *id, struct Ipo *ipo);
+void do_ipo_nocalc(struct Ipo *ipo);
+void do_ipo(struct Ipo *ipo);
+void do_mat_ipo(struct Material *ma);
+void do_ob_ipo(struct Object *ob);
+void do_seq_ipo(struct Sequence *seq);
+int has_ipo_code(struct Ipo *ipo, int code);
+void do_all_ipos(void);
+int calc_ipo_spec(struct Ipo *ipo, int adrcode, float *ctime);
+void clear_delta_obipo(struct Ipo *ipo);
+void add_to_cfra_elem(struct ListBase *lb, struct BezTriple *bezt);
+void make_cfra_list(struct Ipo *ipo, struct ListBase *elems);
+/* the sort is an IPO_Channel... */
+int IPO_GetChannels(struct Ipo *ipo, short *channels);
+void test_ipo_get(void);
+
+float IPO_GetFloatValue(struct Ipo *ipo,
+/* struct IPO_Channel channel, */
+ /* channels are shorts... bit ugly for now*/
+ short c,
+ float ctime);
+
+
+#endif
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
new file mode 100644
index 00000000000..4ad76e3943c
--- /dev/null
+++ b/source/blender/blenkernel/BKE_key.h
@@ -0,0 +1,69 @@
+/**
+ * blenlib/BKE_key.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_KEY_H
+#define BKE_KEY_H
+
+struct Key;
+struct KeyBlock;
+struct ID;
+struct ListBase;
+struct Curve;
+struct Object;
+struct Lattice;
+struct Mesh;
+
+void free_key(struct Key *sc);
+struct Key *add_key(struct ID *id);
+struct Key *copy_key(struct Key *key);
+void make_local_key(struct Key *key);
+void sort_keys(struct Key *key);
+void set_four_ipo(float d, float *data, int type);
+void set_afgeleide_four_ipo(float d, float *data, int type);
+int setkeys(float fac, struct ListBase *lb, struct KeyBlock *k[], float *t, int cycl);
+void flerp(int aantal, float *in, float *f0, float *f1, float *f2, float *f3, float *t);
+void cp_key(int start, int end, int tot, char *poin, struct Key *key, struct KeyBlock *k, int mode);
+void cp_cu_key(struct Curve *cu, struct KeyBlock *kb, int start, int end);
+void rel_flerp(int aantal, float *in, float *ref, float *out, float fac);
+void do_rel_key(int start, int end, int tot, char *basispoin, struct Key *key, float ctime, int mode);
+void do_key(int start, int end, int tot, char *poin, struct Key *key, struct KeyBlock **k, float *t, int mode);
+void do_mesh_key(struct Mesh *me);
+void do_cu_key(struct Curve *cu, struct KeyBlock **k, float *t);
+void do_rel_cu_key(struct Curve *cu, float ctime);
+void do_curve_key(struct Curve *cu);
+void do_latt_key(struct Lattice *lt);
+void do_all_keys(void);
+void do_ob_key(struct Object *ob);
+void do_spec_key(struct Key *key);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
new file mode 100644
index 00000000000..747dc27e175
--- /dev/null
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -0,0 +1,59 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * june-2001 ton
+ */
+
+#ifndef BKE_LATTICE_H
+#define BKE_LATTICE_H
+
+struct Lattice;
+struct Object;
+struct BPoint;
+
+extern struct Lattice *editLatt;
+extern int lt_applyflag;
+
+
+void resizelattice(struct Lattice *lt);
+struct Lattice *add_lattice(void);
+struct Lattice *copy_lattice(struct Lattice *lt);
+void free_lattice(struct Lattice *lt);
+void make_local_lattice(struct Lattice *lt);
+void calc_lat_fudu(int flag, int res, float *fu, float *du);
+void init_latt_deform(struct Object *oblatt, struct Object *ob);
+void calc_latt_deform(float *co);
+void end_latt_deform(void);
+int object_deform(struct Object *ob);
+struct BPoint *latt_bp(struct Lattice *lt, int u, int v, int w);
+void outside_lattice(struct Lattice *lt);
+
+
+#endif
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
new file mode 100644
index 00000000000..4e8c9a61c19
--- /dev/null
+++ b/source/blender/blenkernel/BKE_library.h
@@ -0,0 +1,69 @@
+/**
+ * blenlib/BKE_library.h (mar-2001 nzc)
+ *
+ * Library
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_LIBRARY_TYPES_H
+#define BKE_LIBRARY_TYPES_H
+
+struct ListBase;
+struct ID;
+struct Main;
+struct Library;
+
+void *alloc_libblock(struct ListBase *lb, short type, char *name);
+void *copy_libblock(void *rt);
+
+void id_lib_extern(struct ID *id);
+void id_us_plus(struct ID *id);
+
+int new_id(struct ListBase *lb, struct ID *id, char *name);
+
+struct ListBase *wich_libbase(struct Main *mainlib, short type);
+int set_listbasepointers(struct Main *main, struct ListBase **lb);
+
+void free_libblock(struct ListBase *lb, void *idv);
+void free_libblock_us(struct ListBase *lb, void *idv);
+void free_main(struct Main *mainvar);
+
+void splitIDname(char *name, char *left, int *nr);
+void rename_id(struct ID *id, char *name);
+void test_idbutton(char *name);
+void all_local(void);
+struct ID *find_id(char *type, char *name);
+void clear_id_newpoins(void);
+
+void IDnames_to_pupstring(char **str, char *title, char *extraops, struct ListBase *lb,struct ID* link, short *nr);
+void IPOnames_to_pupstring(char **str, char *title, char *extraops, struct ListBase *lb, struct ID* link, short *nr, int blocktype);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
new file mode 100644
index 00000000000..2e16db34e00
--- /dev/null
+++ b/source/blender/blenkernel/BKE_main.h
@@ -0,0 +1,80 @@
+/**
+ * blenlib/BKE_main.h (mar-2001 nzc)
+ *
+ * Main is the root of the 'database' of a Blender context. All data
+ * is stuffed into lists, and all these lists are knotted to here. A
+ * Blender file is not much more but a binary dump of these
+ * lists. This list of lists is not serialized itself.
+ *
+ * Oops... this should be a _types.h file.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_MAIN_H
+#define BKE_MAIN_H
+
+#include "DNA_listBase.h"
+
+struct Library;
+
+typedef struct Main {
+ struct Main *next, *prev;
+ char name[160];
+ short versionfile, rt;
+ struct Library *curlib;
+ ListBase scene;
+ ListBase library;
+ ListBase object;
+ ListBase mesh;
+ ListBase curve;
+ ListBase mball;
+ ListBase mat;
+ ListBase tex;
+ ListBase image;
+ ListBase ika;
+ ListBase wave;
+ ListBase latt;
+ ListBase lamp;
+ ListBase camera;
+ ListBase ipo;
+ ListBase key;
+ ListBase world;
+ ListBase screen;
+ ListBase vfont;
+ ListBase text;
+ ListBase sound;
+ ListBase group;
+ ListBase armature; /* NLA */
+ ListBase action; /* NLA */
+} Main;
+
+
+#endif
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
new file mode 100644
index 00000000000..8533505776e
--- /dev/null
+++ b/source/blender/blenkernel/BKE_material.h
@@ -0,0 +1,68 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * General operations, lookup, etc. for materials.
+ */
+
+#ifndef BKE_MATERIAL_H
+#define BKE_MATERIAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Material;
+struct ID;
+struct Object;
+
+void free_material(struct Material *sc);
+void test_object_materials(struct ID *id);
+void init_material(struct Material *ma);
+struct Material *add_material(char *name);
+struct Material *copy_material(struct Material *ma);
+void make_local_material(struct Material *ma);
+struct Material ***give_matarar(struct Object *ob);
+short *give_totcolp(struct Object *ob);
+struct Material *give_current_material(struct Object *ob, int act);
+ID *material_from(struct Object *ob, int act);
+void assign_material(struct Object *ob, struct Material *ma, int act);
+void new_material_to_objectdata(struct Object *ob);
+void init_render_material(struct Material *ma);
+void init_render_materials(void);
+void end_render_material(struct Material *ma);
+void end_render_materials(void);
+void automatname(struct Material *ma);
+void delete_material_index(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
new file mode 100644
index 00000000000..c04ce03f176
--- /dev/null
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -0,0 +1,64 @@
+/**
+ * blenlib/BKE_mball.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_MBALL_H
+#define BKE_MBALL_H
+
+struct MetaBall;
+struct Object;
+struct MetaElem;
+struct VERTICES;
+struct VERTEX;
+struct MB_POINT;
+struct PROCESS;
+struct CUBE;
+struct PROCESS;
+
+void unlink_mball(struct MetaBall *mb);
+void free_mball(struct MetaBall *mb);
+struct MetaBall *add_mball(void);
+struct MetaBall *copy_mball(struct MetaBall *mb);
+void make_local_mball(struct MetaBall *mb);
+void tex_space_mball( struct Object *ob);
+void make_orco_mball( struct Object *ob);
+struct Object *find_basis_mball( struct Object *ob);
+void metaball_polygonize(struct Object *ob);
+void calc_mballco(struct MetaElem *ml, float *vec);
+float densfunc(struct MetaElem *ball, float x, float y, float z);
+float metaball(float x, float y, float z);
+void accum_mballfaces(int i1, int i2, int i3, int i4);
+void *new_pgn_element(int size);
+int nextcwedge (int edge, int face);
+void BKE_freecubetable(void);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
new file mode 100644
index 00000000000..1f551f8afe0
--- /dev/null
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -0,0 +1,116 @@
+/**
+ * blenlib/BKE_mesh.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_MESH_H
+#define BKE_MESH_H
+
+/* texflag */
+#define AUTOSPACE 1
+
+/* me->flag (let op alternatieven in blendpsx.h) */
+#define ME_ISDONE 1
+#define ME_NOPUNOFLIP 2
+#define ME_TWOSIDED 4
+#define ME_UVEFFECT 8
+#define ME_VCOLEFFECT 16
+#define ME_AUTOSMOOTH 32
+#define ME_SMESH 64
+#define ME_SUBSURF 128
+
+/* puno (mface) */
+#define ME_FLIPV1 1
+#define ME_FLIPV2 2
+#define ME_FLIPV3 4
+#define ME_FLIPV4 8
+#define ME_PROJXY 16
+#define ME_PROJXZ 32
+#define ME_PROJYZ 64
+
+/* edcode (mface) */
+#define ME_V1V2 1
+#define ME_V2V3 2
+#define ME_V3V1 4
+#define ME_V3V4 4
+#define ME_V4V1 8
+
+/* flag (mface) */
+#define ME_SMOOTH 1
+
+/***/
+
+struct DispList;
+struct ListBase;
+struct MDeformVert;
+struct Mesh;
+struct MFace;
+struct MVert;
+struct Object;
+struct TFace;
+struct VecNor;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void unlink_mesh(struct Mesh *me);
+void free_mesh(struct Mesh *me);
+struct Mesh *add_mesh(void);
+struct Mesh *copy_mesh(struct Mesh *me);
+void make_local_tface(struct Mesh *me);
+void make_local_mesh(struct Mesh *me);
+void boundbox_mesh(struct Mesh *me, float *loc, float *size);
+void tex_space_mesh(struct Mesh *me);
+void make_orco_displist_mesh(struct Object *ob, int subdivlvl);
+void make_orco_mesh(struct Mesh *me);
+void test_index_mface(struct MFace *mface, int nr);
+void test_index_face(struct MFace *mface, struct TFace *tface, int nr);
+void flipnorm_mesh(struct Mesh *me);
+struct Mesh *get_mesh(struct Object *ob);
+void set_mesh(struct Object *ob, struct Mesh *me);
+void mball_to_mesh(struct ListBase *lb, struct Mesh *me);
+void nurbs_to_mesh(struct Object *ob);
+void edge_drawflags_mesh(struct Mesh *me);
+void mcol_to_tface(struct Mesh *me, int freedata);
+void tface_to_mcol(struct Mesh *me);
+void free_dverts(struct MDeformVert *dvert, int totvert);
+void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); /* __NLA */
+int mesh_uses_displist(struct Mesh *me);
+int rendermesh_uses_displist(struct Mesh *me);
+float get_mvert_weight (struct Object *ob, int vert, int defgroup);
+int update_realtime_texture(struct TFace *tface, double time);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h
new file mode 100644
index 00000000000..9f1ad39f7a6
--- /dev/null
+++ b/source/blender/blenkernel/BKE_nla.h
@@ -0,0 +1,46 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BKE_NLA_H
+#define BKE_NLA_H
+
+struct bActionStrip;
+struct ListBase;
+
+void free_actionstrip(struct bActionStrip* strip);
+void free_nlastrips (struct ListBase *nlalist);
+void copy_nlastrips (struct ListBase *dst, struct ListBase *src);
+void copy_actionstrip (struct bActionStrip **dst, struct bActionStrip **src);
+
+#endif
+
+
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
new file mode 100644
index 00000000000..b29a051a4db
--- /dev/null
+++ b/source/blender/blenkernel/BKE_object.h
@@ -0,0 +1,99 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * General operations, lookup, etc. for blender objects.
+ */
+
+#ifndef BKE_OBJECT_H
+#define BKE_OBJECT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Base;
+struct Object;
+struct Camera;
+struct BoundBox;
+struct View3D;
+
+void clear_workob(void);
+void copy_baseflags(void);
+void copy_objectflags(void);
+void update_base_layer(struct Object *ob);
+void free_object(struct Object *ob);
+void unlink_object(struct Object *ob);
+int exist_object(struct Object *obtest);
+void *add_camera(void);
+struct Camera *copy_camera(struct Camera *cam);
+void make_local_camera(struct Camera *cam);
+void *add_lamp(void);
+struct Lamp *copy_lamp(struct Lamp *la);
+void make_local_lamp(struct Lamp *la);
+void free_camera(struct Camera *ca);
+void free_lamp(struct Lamp *la);
+void *add_wave(void);
+
+struct Object *add_object(int type);
+void base_init_from_view3d(struct Base *base, struct View3D *v3d);
+
+struct Object *copy_object(struct Object *ob);
+void expand_local_object(struct Object *ob);
+void make_local_object(struct Object *ob);
+void set_mblur_offs(int blur);
+void disable_speed_curve(int val);
+float bsystem_time(struct Object *ob, struct Object *par, float cfra, float ofs);
+void object_to_mat3(struct Object *ob, float mat[][3]);
+void object_to_mat4(struct Object *ob, float mat[][4]);
+void ob_parcurve(struct Object *ob, struct Object *par, float mat[][4]);
+void ob_parlimb(struct Object *ob, struct Object *par, float mat[][4]);
+void ob_parbone(struct Object *ob, struct Object *par, float mat[][4]); /* __NLA */
+void give_parvert(struct Object *par, int nr, float *vec);
+void ob_parvert3(struct Object *ob, struct Object *par, float mat[][4]);
+void set_no_parent_ipo(int val);
+void set_dtime(int dtime);
+void disable_where_script(short on);
+int during_script(void);
+void where_is_object_time(struct Object *ob, float ctime);
+void where_is_object(struct Object *ob);
+void where_is_object_simul(struct Object *ob);
+void what_does_parent1(struct Object *par, int partype, int par1, int par2, int par3);
+void what_does_parent(struct Object *ob);
+struct BoundBox *unit_boundbox(void);
+void minmax_object(struct Object *ob, float *min, float *max);
+void solve_tracking (struct Object *ob, float targetmat[][4]);
+void solve_constraints (struct Object *ob, short obtype, void *obdata, float ctime);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_osa_types.h b/source/blender/blenkernel/BKE_osa_types.h
new file mode 100644
index 00000000000..f6ccf5e7e31
--- /dev/null
+++ b/source/blender/blenkernel/BKE_osa_types.h
@@ -0,0 +1,53 @@
+/**
+ * blenlib/BKE_osa_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_OSA_TYPES_H
+#define BKE_OSA_TYPES_H
+
+/* typedef struct Osa */
+typedef struct RE_Osa
+{
+ float dxco[3], dyco[3];
+ float dxlo[3], dylo[3], dxgl[3], dygl[3], dxuv[3], dyuv[3];
+ float dxref[3], dyref[3], dxorn[3], dyorn[3];
+ float dxno[3], dyno[3], dxview, dyview;
+ float dxlv[3], dylv[3];
+ float dxwin[3], dywin[3];
+ float dxsticky[3], dysticky[3];
+} Osa;
+
+/* extern Osa O; */
+/* This one used to be done in render/extern/include/render.h, because
+ memory was allocated in that module. (nzc)*/
+
+#endif
diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h
new file mode 100644
index 00000000000..16b6c996aab
--- /dev/null
+++ b/source/blender/blenkernel/BKE_packedFile.h
@@ -0,0 +1,61 @@
+/**
+ * blenlib/BKE_packedFile.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_PACKEDFILE_H
+#define BKE_PACKEDFILE_H
+
+struct PackedFile;
+struct VFont;
+struct bSample;
+struct bSound;
+struct Image;
+
+struct PackedFile * newPackedFile(char * filename);
+struct PackedFile * newPackedFileMemory(void *mem, int memlen);
+
+int seekPackedFile(struct PackedFile * pf, int offset, int whence);
+void rewindPackedFile(struct PackedFile * pf);
+int readPackedFile(struct PackedFile * pf, void * data, int size);
+int countPackedFiles(void);
+void freePackedFile(struct PackedFile * pf);
+void packAll(void);
+int writePackedFile(char * filename, struct PackedFile *pf);
+int checkPackedFile(char * filename, struct PackedFile * pf);
+char * unpackFile(char * abs_name, char * local_name, struct PackedFile * pf, int how);
+int unpackVFont(struct VFont * vfont, int how);
+void create_local_name(char *localname, char *prefix, char *filename);
+int unpackSample(struct bSample *sample, int how);
+int unpackImage(struct Image * ima, int how);
+void unpackAll(int how);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_plugin_types.h b/source/blender/blenkernel/BKE_plugin_types.h
new file mode 100644
index 00000000000..3da89561aac
--- /dev/null
+++ b/source/blender/blenkernel/BKE_plugin_types.h
@@ -0,0 +1,70 @@
+/**
+ * blenlib/BKE_plugin_types.h (mar-2001 nzc)
+ *
+ * Renderrecipe and scene decription. The fact that there is a
+ * hierarchy here is a bit strange, and not desirable.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_PLUGIN_TYPES_H
+#define BKE_PLUGIN_TYPES_H
+
+struct ImBuf;
+
+typedef int (*TexDoit)(int, void*, float*, float*, float*);
+typedef void (*SeqDoit)(void*, float, float, int, int,
+ struct ImBuf*, struct ImBuf*,
+ struct ImBuf*, struct ImBuf*);
+
+typedef struct VarStruct {
+ int type;
+ char name[16];
+ float def, min, max;
+ char tip[80];
+} VarStruct;
+
+typedef struct _PluginInfo {
+ char *name;
+ char *snames;
+
+ int stypes;
+ int nvars;
+ VarStruct *varstr;
+ float *result;
+ float *cfra;
+
+ void (*init)(void);
+ void (*callback)(int);
+ TexDoit tex_doit;
+ SeqDoit seq_doit;
+} PluginInfo;
+
+#endif
diff --git a/source/blender/blenkernel/BKE_property.h b/source/blender/blenkernel/BKE_property.h
new file mode 100644
index 00000000000..8dd3f3e085b
--- /dev/null
+++ b/source/blender/blenkernel/BKE_property.h
@@ -0,0 +1,54 @@
+/**
+ * blenkernel/BKE_property.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_PROPERTY_H
+#define BKE_PROPERTY_H
+
+struct bProperty;
+struct ListBase;
+struct Object;
+
+void free_property(struct bProperty *prop);
+void free_properties(struct ListBase *lb);
+struct bProperty *copy_property(struct bProperty *prop);
+void copy_properties(struct ListBase *lbn, struct ListBase *lbo);
+void init_property(struct bProperty *prop);
+struct bProperty *new_property(int type);
+struct bProperty *get_property(struct Object *ob, char *name);
+int compare_property(struct bProperty *prop, char *str);
+void set_property(struct bProperty *prop, char *str);
+void add_property(struct bProperty *prop, char *str);
+void set_property_valstr(struct bProperty *prop, char *str);
+void cp_property(struct bProperty *prop1, struct bProperty *prop2);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h
new file mode 100644
index 00000000000..c3ad581852d
--- /dev/null
+++ b/source/blender/blenkernel/BKE_sca.h
@@ -0,0 +1,74 @@
+/**
+ * blenlib/BKE_sca.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_SCA_H
+#define BKE_SCA_H
+
+struct Text;
+struct bSensor;
+struct Object;
+struct bController;
+struct bActuator;
+
+void unlink_controller(struct bController *cont);
+void unlink_controllers(struct ListBase *lb);
+void free_controller(struct bController *cont);
+void free_controllers(struct ListBase *lb);
+
+void unlink_actuator(struct bActuator *act);
+void unlink_actuators(struct ListBase *lb);
+void free_actuator(struct bActuator *act);
+void free_actuators(struct ListBase *lb);
+
+void free_text_controllers(struct Text *txt);
+void free_sensor(struct bSensor *sens);
+void free_sensors(struct ListBase *lb);
+struct bSensor *copy_sensor(struct bSensor *sens);
+void copy_sensors(struct ListBase *lbn, struct ListBase *lbo);
+void init_sensor(struct bSensor *sens);
+struct bSensor *new_sensor(int type);
+struct bController *copy_controller(struct bController *cont);
+void copy_controllers(struct ListBase *lbn, struct ListBase *lbo);
+void init_controller(struct bController *cont);
+struct bController *new_controller(int type);
+struct bActuator *copy_actuator(struct bActuator *act);
+void copy_actuators(struct ListBase *lbn, struct ListBase *lbo);
+void init_actuator(struct bActuator *act);
+struct bActuator *new_actuator(int type);
+void clear_sca_new_poins_ob(struct Object *ob);
+void clear_sca_new_poins(void);
+void set_sca_new_poins_ob(struct Object *ob);
+void set_sca_new_poins(void);
+void sca_remove_ob_poin(struct Object *obt, struct Object *ob);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
new file mode 100644
index 00000000000..ff4b4c6f258
--- /dev/null
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -0,0 +1,56 @@
+/**
+ * blenlib/BKE_scene.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_SCENE_H
+#define BKE_SCENE_H
+
+struct Scene;
+struct Object;
+struct Base;
+struct AviCodecData;
+
+void free_avicodecdata(struct AviCodecData *acd);
+void free_scene(struct Scene *me);
+struct Scene *add_scene(char *name);
+int object_in_scene(struct Object *ob, struct Scene *sce);
+void sort_baselist(struct Scene *sce);
+void set_scene_bg(struct Scene *sce);
+void set_scene_name(char *name);
+int next_object(int val, struct Base **base, struct Object **ob);
+struct Object *scene_find_camera(struct Scene *sc);
+
+struct Base *scene_add_base(struct Scene *sce, struct Object *ob);
+void scene_deselect_all(struct Scene *sce);
+void scene_select_base(struct Scene *sce, struct Base *selbase);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
new file mode 100644
index 00000000000..b64caa6dfef
--- /dev/null
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -0,0 +1,40 @@
+/**
+ * blenlib/BKE_screen.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_SCREEN_H
+#define BKE_SCREEN_H
+
+void free_screen(struct bScreen *sc);
+
+
+#endif
diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h
new file mode 100644
index 00000000000..3010bc2d87a
--- /dev/null
+++ b/source/blender/blenkernel/BKE_sound.h
@@ -0,0 +1,51 @@
+/**
+ * sound.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_SOUND_H
+#define BKE_SOUND_H
+
+struct PackedFile;
+struct bSound;
+struct bSample;
+struct ListBase;
+
+extern struct ListBase *samples;
+
+/* void *sound_get_listener(void); implemented in src!also declared there now */
+
+void sound_set_packedfile(struct bSample* sample, struct PackedFile* pf);
+struct PackedFile* sound_find_packedfile(struct bSound* sound);
+void sound_free_sample(struct bSample* sample);
+void sound_free_sound(struct bSound* sound);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h
new file mode 100644
index 00000000000..745ecb0cdd4
--- /dev/null
+++ b/source/blender/blenkernel/BKE_subsurf.h
@@ -0,0 +1,43 @@
+/* $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_SUBSURF_H
+#define BKE_SUBSURF_H
+
+struct Mesh;
+struct Object;
+struct Displist;
+
+void subsurf_to_mesh(struct Object *oldob, struct Mesh *newme);
+void subsurf_make_mesh(struct Object *ob, short subdiv);
+void subsurf_make_editmesh(struct Object *ob);
+struct DispList* subsurf_mesh_to_displist(struct Mesh *me, struct DispList *dl, short subdiv);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
new file mode 100644
index 00000000000..43e3bb76b12
--- /dev/null
+++ b/source/blender/blenkernel/BKE_text.h
@@ -0,0 +1,128 @@
+/**
+ * blenlib/BKE_text.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_TEXT_H
+#define BKE_TEXT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Text;
+struct TextLine;
+
+void free_text (struct Text *text);
+void txt_set_undostate (int u);
+int txt_get_undostate (void);
+struct Text* add_empty_text (void);
+int reopen_text (struct Text *text);
+struct Text* add_text (char *file);
+struct Text* copy_text (struct Text *ta);
+
+void txt_free_cut_buffer (void);
+
+char* txt_to_buf (struct Text *text);
+void txt_clean_text (struct Text *text);
+void txt_order_cursors (struct Text *text);
+int txt_find_string (struct Text *text, char *findstr);
+int txt_has_sel (struct Text *text);
+int txt_get_span (struct TextLine *from, struct TextLine *to);
+void txt_move_up (struct Text *text, short sel);
+void txt_move_down (struct Text *text, short sel);
+void txt_move_left (struct Text *text, short sel);
+void txt_move_right (struct Text *text, short sel);
+void txt_move_bof (struct Text *text, short sel);
+void txt_move_eof (struct Text *text, short sel);
+void txt_move_bol (struct Text *text, short sel);
+void txt_move_eol (struct Text *text, short sel);
+void txt_move_toline (struct Text *text, unsigned int line, short sel);
+void txt_pop_sel (struct Text *text);
+void txt_delete_char (struct Text *text);
+void txt_copy_sel (struct Text *text);
+void txt_sel_all (struct Text *text);
+void txt_sel_line (struct Text *text);
+void txt_print_cutbuffer (void);
+void txt_cut_sel (struct Text *text);
+char* txt_sel_to_buf (struct Text *text);
+void txt_insert_buf (struct Text *text, char *in_buffer);
+void txt_paste (struct Text *text);
+void txt_print_undo (struct Text *text);
+void txt_undo_add_toop (struct Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc);
+void txt_do_undo (struct Text *text);
+void txt_do_redo (struct Text *text);
+void txt_split_curline (struct Text *text);
+void txt_backspace_char (struct Text *text);
+int txt_add_char (struct Text *text, char add);
+
+
+/* Undo opcodes */
+
+/* Simple main cursor movement */
+#define UNDO_CLEFT 001
+#define UNDO_CRIGHT 002
+#define UNDO_CUP 003
+#define UNDO_CDOWN 004
+
+/* Simple selection cursor movement */
+#define UNDO_SLEFT 005
+#define UNDO_SRIGHT 006
+#define UNDO_SUP 007
+#define UNDO_SDOWN 021
+
+/* Complex movement (opcode is followed
+ * by 4 character line ID + a 2 character
+ * position ID and opcode (repeat)) */
+#define UNDO_CTO 022
+#define UNDO_STO 023
+
+/* Complex editing (opcode is followed
+ * by 1 character ID and opcode (repeat)) */
+#define UNDO_INSERT 024
+#define UNDO_BS 025
+#define UNDO_DEL 026
+
+/* Text block (opcode is followed
+ * by 4 character length ID + the text
+ * block itself + the 4 character length
+ * ID (repeat) and opcode (repeat)) */
+#define UNDO_DBLOCK 027 /* Delete block */
+#define UNDO_IBLOCK 030 /* Insert block */
+
+/* Misc */
+#define UNDO_SWAP 031 /* Swap cursors */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
new file mode 100644
index 00000000000..172afcaecd6
--- /dev/null
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -0,0 +1,85 @@
+/**
+ * blenlib/BKE_texture.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_TEXTURE_H
+#define BKE_TEXTURE_H
+
+struct Tex;
+struct MTex;
+struct PluginTex;
+struct LampRen;
+struct ColorBand;
+struct HaloRen;
+
+/* in ColorBand struct */
+#define MAXCOLORBAND 16
+
+
+void free_texture(struct Tex *t);
+int test_dlerr(const char *name, const char *symbol);
+void open_plugin_tex(struct PluginTex *pit);
+struct PluginTex *add_plugin_tex(char *str);
+void free_plugin_tex(struct PluginTex *pit);
+struct ColorBand *add_colorband(void);
+int do_colorband(struct ColorBand *coba);
+void default_tex(struct Tex *tex);
+struct Tex *add_texture(char *name);
+void default_mtex(struct MTex *mtex);
+struct MTex *add_mtex(void);
+struct Tex *copy_texture(struct Tex *tex);
+void make_local_texture(struct Tex *tex);
+void autotexname(struct Tex *tex);
+void init_render_texture(struct Tex *tex);
+void init_render_textures(void);
+void end_render_texture(struct Tex *tex);
+void end_render_textures(void);
+int clouds(struct Tex *tex, float *texvec);
+int blend(struct Tex *tex, float *texvec);
+int wood(struct Tex *tex, float *texvec);
+int marble(struct Tex *tex, float *texvec);
+int magic(struct Tex *tex, float *texvec);
+int stucci(struct Tex *tex, float *texvec);
+int texnoise(struct Tex *tex);
+int plugintex(struct Tex *tex, float *texvec, float *dxt, float *dyt);
+void tubemap(float x, float y, float z, float *adr1, float *adr2);
+void spheremap(float x, float y, float z, float *adr1, float *adr2);
+void do_2d_mapping(struct MTex *mtex, float *t, float *dxt, float *dyt);
+int multitex(struct Tex *tex, float *texvec, float *dxt, float *dyt);
+void do_material_tex(void);
+void do_halo_tex(struct HaloRen *har, float xn, float yn, float *colf);
+void do_sky_tex(void);
+void do_lamp_tex(struct LampRen *la, float *lavec);
+void externtex(struct MTex *mtex, float *vec);
+void externtexcol(struct MTex *mtex, float *orco, char *col);
+void render_realtime_texture(void);
+#endif
diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h
new file mode 100644
index 00000000000..65bad0f40b3
--- /dev/null
+++ b/source/blender/blenkernel/BKE_utildefines.h
@@ -0,0 +1,300 @@
+/* util defines -- might go away ?*/
+
+/*
+ $Id$
+
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+#ifndef BKE_UTILDEFINES_H
+#define BKE_UTILDEFINES_H
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#define ELEM(a, b, c) ( (a)==(b) || (a)==(c) )
+#define ELEM3(a, b, c, d) ( ELEM(a, b, c) || (a)==(d) )
+#define ELEM4(a, b, c, d, e) ( ELEM(a, b, c) || ELEM(a, d, e) )
+#define ELEM5(a, b, c, d, e, f) ( ELEM(a, b, c) || ELEM3(a, d, e, f) )
+#define ELEM6(a, b, c, d, e, f, g) ( ELEM(a, b, c) || ELEM4(a, d, e, f, g) )
+#define ELEM7(a, b, c, d, e, f, g, h) ( ELEM3(a, b, c, d) || ELEM4(a, e, f, g, h) )
+#define ELEM8(a, b, c, d, e, f, g, h, i) ( ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) )
+
+
+/* string compare */
+#define STREQ(str, a) ( strcmp((str), (a))==0 )
+#define STREQ2(str, a, b) ( STREQ(str, a) || STREQ(str, b) )
+#define STREQ3(str, a, b, c) ( STREQ2(str, a, b) || STREQ(str, c) )
+
+/* min/max */
+#define MIN2(x,y) ( (x)<(y) ? (x) : (y) )
+#define MIN3(x,y,z) MIN2( MIN2((x),(y)) , (z) )
+#define MIN4(x,y,z,a) MIN2( MIN2((x),(y)) , MIN2((z),(a)) )
+
+#define MAX2(x,y) ( (x)>(y) ? (x) : (y) )
+#define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) )
+#define MAX4(x,y,z,a) MAX2( MAX2((x),(y)) , MAX2((z),(a)) )
+
+#define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; }
+
+#define ABS(a) ( (a)<0 ? (-a) : (a) )
+
+#define VECCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2);}
+#define QUATCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2); *(v1+3)= *(v2+3);}
+
+#define INIT_MINMAX(min, max) (min)[0]= (min)[1]= (min)[2]= 1.0e30; (max)[0]= (max)[1]= (max)[2]= -1.0e30;
+
+#define DO_MINMAX(vec, min, max) if( (min)[0]>(vec)[0] ) (min)[0]= (vec)[0]; \
+ if( (min)[1]>(vec)[1] ) (min)[1]= (vec)[1]; \
+ if( (min)[2]>(vec)[2] ) (min)[2]= (vec)[2]; \
+ if( (max)[0]<(vec)[0] ) (max)[0]= (vec)[0]; \
+ if( (max)[1]<(vec)[1] ) (max)[1]= (vec)[1]; \
+ if( (max)[2]<(vec)[2] ) (max)[2]= (vec)[2]; \
+
+#define DO_MINMAX2(vec, min, max) if( (min)[0]>(vec)[0] ) (min)[0]= (vec)[0]; \
+ if( (min)[1]>(vec)[1] ) (min)[1]= (vec)[1]; \
+ if( (max)[0]<(vec)[0] ) (max)[0]= (vec)[0]; \
+ if( (max)[1]<(vec)[1] ) (max)[1]= (vec)[1];
+
+
+/* interferes elsewhere */
+/* deze getallen ook invullen in blender.h SpaceFile: struct dna herkent geen defines */
+#define FILE_MAXDIR 160
+#define FILE_MAXFILE 80
+
+
+/* some misc stuff.... */
+#define CLAMP(a, b, c) if((a)<(b)) (a)=(b); else if((a)>(c)) (a)=(c)
+
+#define KNOTSU(nu) ( (nu)->orderu+ (nu)->pntsu+ (nu->orderu-1)*((nu)->flagu & 1) )
+#define KNOTSV(nu) ( (nu)->orderv+ (nu)->pntsv+ (nu->orderv-1)*((nu)->flagv & 1) )
+
+/* this weirdo pops up in two places ... */
+#if !defined(WIN32) && !defined(__BeOS)
+#define O_BINARY 0
+#endif
+
+/* INTEGER CODES */
+#if defined(__sgi) || defined (__sparc) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+ /* Big Endian */
+#define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
+#else
+ /* Little Endian */
+#define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
+#endif
+
+#define ID_NEW(a) if( (a) && (a)->id.newid ) (a)= (void *)(a)->id.newid
+
+#define FORM MAKE_ID('F','O','R','M')
+#define DDG1 MAKE_ID('3','D','G','1')
+#define DDG2 MAKE_ID('3','D','G','2')
+#define DDG3 MAKE_ID('3','D','G','3')
+#define DDG4 MAKE_ID('3','D','G','4')
+
+#define GOUR MAKE_ID('G','O','U','R')
+
+#define BLEN MAKE_ID('B','L','E','N')
+#define DER_ MAKE_ID('D','E','R','_')
+#define V100 MAKE_ID('V','1','0','0')
+
+#define DATA MAKE_ID('D','A','T','A')
+#define GLOB MAKE_ID('G','L','O','B')
+#define IMAG MAKE_ID('I','M','A','G')
+
+#define DNA1 MAKE_ID('D','N','A','1')
+#define TEST MAKE_ID('T','E','S','T')
+#define REND MAKE_ID('R','E','N','D')
+#define USER MAKE_ID('U','S','E','R')
+
+#define ENDB MAKE_ID('E','N','D','B')
+
+/* This should, of course, become a function */
+#define DL_SURFINDEX(cyclu, cyclv, sizeu, sizev) \
+ \
+ if( (cyclv)==0 && a==(sizev)-1) break; \
+ if(cyclu) { \
+ p1= sizeu*a; \
+ p2= p1+ sizeu-1; \
+ p3= p1+ sizeu; \
+ p4= p2+ sizeu; \
+ b= 0; \
+ } \
+ else { \
+ p2= sizeu*a; \
+ p1= p2+1; \
+ p4= p2+ sizeu; \
+ p3= p1+ sizeu; \
+ b= 1; \
+ } \
+ if( (cyclv) && a==sizev-1) { \
+ p3-= sizeu*sizev; \
+ p4-= sizeu*sizev; \
+ }
+
+/* This one rotates the bytes in an int */
+#define SWITCH_INT(a) { \
+ char s_i, *p_i; \
+ p_i= (char *)&(a); \
+ s_i=p_i[0]; p_i[0]=p_i[3]; p_i[3]=s_i; \
+ s_i=p_i[1]; p_i[1]=p_i[2]; p_i[2]=s_i; }
+
+/* More brain damage. Only really used by packedFile.c */
+// return values
+#define RET_OK 0
+#define RET_ERROR 1
+/* and these aren't used at all */
+/* #define RET_CANCEL 2 */
+/* #define RET_YES (1 == 1) */
+/* #define RET_NO (1 == 0) */
+
+/* sequence related defines */
+#define WHILE_SEQ(base) { \
+ int totseq_, seq_; Sequence **seqar; \
+ build_seqar( base, &seqar, &totseq_); \
+ for(seq_ = 0; seq_ < totseq_; seq_++) { \
+ seq= seqar[seq_];
+
+
+#define END_SEQ } \
+ if(seqar) MEM_freeN(seqar); \
+ }
+
+
+/* not really sure about these... some kind of event codes ?*/
+/* INFO: 300 */
+/* pas op: ook in filesel.c en editobject.c */
+#define B_INFOSCR 301
+#define B_INFODELSCR 302
+#define B_INFOSCE 304
+#define B_INFODELSCE 305
+#define B_FILEMENU 306
+#define B_PACKFILE 307
+
+/* From iff.h, but seemingly detached from anything else... To which
+ * encoding scheme do they belong? */
+#define AMI (1 << 31)
+#define CDI (1 << 30)
+#define Anim (1 << 29)
+#define TGA (1 << 28)
+#define JPG (1 << 27)
+#define TIM (1 << 26)
+
+#define TIM_CLUT (010)
+#define TIM_4 (TIM | TIM_CLUT | 0)
+#define TIM_8 (TIM | TIM_CLUT | 1)
+#define TIM_16 (TIM | 2)
+#define TIM_24 (TIM | 3)
+
+#define RAWTGA (TGA | 1)
+
+#define JPG_STD (JPG | (0 << 8))
+#define JPG_VID (JPG | (1 << 8))
+#define JPG_JST (JPG | (2 << 8))
+#define JPG_MAX (JPG | (3 << 8))
+#define JPG_MSK (0xffffff00)
+
+#define AM_ham (0x0800 | AMI)
+#define AM_hbrite (0x0080 | AMI)
+#define AM_lace (0x0004 | AMI)
+#define AM_hires (0x8000 | AMI)
+#define AM_hblace (AM_hbrite | AM_lace)
+#define AM_hilace (AM_hires | AM_lace)
+#define AM_hamlace (AM_ham | AM_lace)
+
+#define RGB888 1
+#define RGB555 2
+#define DYUV 3
+#define CLUT8 4
+#define CLUT7 5
+#define CLUT4 6
+#define CLUT3 7
+#define RL7 8
+#define RL3 9
+#define MPLTE 10
+
+#define DYUV1 0
+#define DYUVE 1
+
+#define CD_rgb8 (RGB888 | CDI)
+#define CD_rgb5 (RGB555 | CDI)
+#define CD_dyuv (DYUV | CDI)
+#define CD_clut8 (CLUT8 | CDI)
+#define CD_clut7 (CLUT7 | CDI)
+#define CD_clut4 (CLUT4 | CDI)
+#define CD_clut3 (CLUT3 | CDI)
+#define CD_rl7 (RL7 | CDI)
+#define CD_rl3 (RL3 | CDI)
+#define CD_mplte (MPLTE | CDI)
+
+#define C233 1
+#define YUVX 2
+#define HAMX 3
+#define TANX 4
+
+#define AN_c233 (Anim | C233)
+#define AN_yuvx (Anim | YUVX)
+#define AN_hamx (Anim | HAMX)
+#define AN_tanx (Anim | TANX)
+
+#define IMAGIC 0732
+
+/* This used to reside in render.h. It does some texturing. */
+#define BRICON Tin= (Tin-0.5)*tex->contrast+tex->bright-0.5; \
+ if(Tin<0.0) Tin= 0.0; else if(Tin>1.0) Tin= 1.0;
+
+#define BRICONRGB Tr= tex->rfac*((Tr-0.5)*tex->contrast+tex->bright-0.5); \
+ if(Tr<0.0) Tr= 0.0; else if(Tr>1.0) Tr= 1.0; \
+ Tg= tex->gfac*((Tg-0.5)*tex->contrast+tex->bright-0.5); \
+ if(Tg<0.0) Tg= 0.0; else if(Tg>1.0) Tg= 1.0; \
+ Tb= tex->bfac*((Tb-0.5)*tex->contrast+tex->bright-0.5); \
+ if(Tb<0.0) Tb= 0.0; else if(Tb>1.0) Tb= 1.0;
+
+/* mystifying stuff from blendef... */
+#define SELECT 1
+#define ACTIVE 2
+#define NOT_YET 0
+
+/* ???? */
+#define BTST(a,b) ( ( (a) & 1<<(b) )!=0 )
+#define BSET(a,b) ( (a) | 1<<(b) )
+
+/* needed for material.c*/
+#define REDRAWBUTSMAT 0x4015
+
+/* useless game shit */
+#define MA_FH_NOR 2
+
+
+#endif
diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h
new file mode 100644
index 00000000000..0ea13557e03
--- /dev/null
+++ b/source/blender/blenkernel/BKE_world.h
@@ -0,0 +1,45 @@
+/**
+ * blenlib/BKE_world.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_WORLD_H
+#define BKE_WORLD_H
+
+struct World;
+
+void free_world(struct World *sc);
+struct World *add_world(char *name);
+struct World *copy_world(struct World *wrld);
+void make_local_world(struct World *wrld);
+void init_render_world(void);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h
new file mode 100644
index 00000000000..f63342ea047
--- /dev/null
+++ b/source/blender/blenkernel/BKE_writeavi.h
@@ -0,0 +1,50 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BKE_WRITEAVI_H
+#define BKE_WRITEAVI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void start_avi(void);
+void end_avi(void);
+void append_avi(int frame);
+void makeavistring(char *string);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/source/blender/blenkernel/Makefile b/source/blender/blenkernel/Makefile
new file mode 100644
index 00000000000..239941ec59b
--- /dev/null
+++ b/source/blender/blenkernel/Makefile
@@ -0,0 +1,37 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/blenkernel
+DIRS = intern bad_level_call_stubs
+
+include nan_subdirs.mk
diff --git a/source/blender/blenkernel/bad_level_call_stubs/Makefile b/source/blender/blenkernel/bad_level_call_stubs/Makefile
new file mode 100644
index 00000000000..2d98ea5a1af
--- /dev/null
+++ b/source/blender/blenkernel/bad_level_call_stubs/Makefile
@@ -0,0 +1,55 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+#
+
+LIBNAME = blenkernel_blc
+DIR = $(OCGDIR)/blender/blenkernel/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+CFLAGS += $(FIX_STUBS_WARNINGS)
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CPPFLAGS += $(OGL_CPPFLAGS)
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../include
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../render/extern/include
+CPPFLAGS += -I$(NAN_IKSOLVER)/include
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
new file mode 100644
index 00000000000..239e4f16487
--- /dev/null
+++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
@@ -0,0 +1,180 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * BKE_bad_level_calls function stubs
+ */
+
+
+#include "BLI_blenlib.h"
+
+#include "DNA_material_types.h"
+
+#include "BKE_bad_level_calls.h"
+
+int winqueue_break= 0;
+
+/* readfile.c */
+ /* struct PluginSeq; */
+void open_plugin_seq(struct PluginSeq *pis, char *seqname){}
+ /* struct SpaceButs; */
+void set_rects_butspace(struct SpaceButs *buts){}
+ /* struct SpaceImaSel; */
+void check_imasel_copy(struct SpaceImaSel *simasel){}
+ /* struct ScrArea; */
+void unlink_screen(struct bScreen *sc){}
+void freeAllRad(void){}
+void free_editText(void){}
+void free_editArmature(void){}
+
+
+void setscreen(struct bScreen *sc){}
+void force_draw_all(void){}
+ /* otherwise the WHILE_SEQ doesn't work */
+ /* struct Sequence; */
+
+/* MAART: added "seqar = 0; totseq = 0" because the loader will crash without it. */
+void build_seqar(ListBase *seqbase, struct Sequence ***seqar, int *totseq)
+{
+ *seqar = 0;
+ *totseq = 0;
+}
+
+void BPY_do_pyscript(ID *id, short int event){}
+void BPY_free_compiled_text(struct Text *text) {};
+
+/* writefile.c */
+ /* struct Oops; */
+void free_oops(struct Oops *oops){}
+void exit_posemode(int freedata){}
+void error(char *str, ...){}
+
+/* anim.c */
+ListBase editNurb;
+
+/* displist.c */
+#include "DNA_world_types.h" /* for render_types */
+#include "render_types.h"
+struct RE_Render R;
+float RE_Spec(float inp, int hard){}
+void waitcursor(int val){}
+void allqueue(unsigned short event, short val){}
+#define REDRAWVIEW3D 0x4010
+Material defmaterial;
+
+/* effect.c */
+void RE_jitterate1(float *jit1, float *jit2, int num, float rad1){}
+void RE_jitterate2(float *jit1, float *jit2, int num, float rad2){}
+
+/* exotic.c */
+void load_editMesh(void){}
+void make_editMesh(void){}
+void free_editMesh(void){}
+void docentre_new(void){}
+int saveover(char *str){}
+
+/* image.c */
+#include "DNA_image_types.h"
+void free_realtime_image(Image *ima){} // has to become a callback, opengl stuff
+void RE_make_existing_file(char *name){} // from render, but these funcs should be moved anyway
+
+/* ipo.c */
+void copy_view3d_lock(short val){} // was a hack, to make scene layer ipo's possible
+
+/* library.c */
+void allspace(unsigned short event, short val){}
+#define OOPS_TEST 2
+
+/* mball.c */
+ListBase editelems;
+
+/* object.c */
+void BPY_free_scriptlink(ScriptLink *slink){}
+void BPY_copy_scriptlink(ScriptLink *scriptlink){}
+float *give_cursor(void){} // become a callback or argument
+
+
+/* packedFile.c */
+short pupmenu(char *instr){} // will be general callback
+
+/* sca.c */
+#define LEFTMOUSE 0x001 // because of mouse sensor
+
+/* scene.c */
+#include "DNA_sequence_types.h"
+void free_editing(struct Editing *ed){} // scenes and sequences problem...
+void BPY_do_all_scripts (short int event){}
+
+/* IKsolver stubs */
+#include "IK_solver.h"
+extern int IK_LoadChain(IK_Chain_ExternPtr chain,IK_Segment_ExternPtr segments, int num_segs)
+{
+ return 0;
+}
+
+extern int IK_SolveChain(
+ IK_Chain_ExternPtr chain,
+ float goal[3],
+ float tolerance,
+ int max_iterations,
+ float max_angle_change,
+ IK_Segment_ExternPtr output
+ )
+{
+ return 0;
+}
+
+extern void IK_FreeChain(IK_Chain_ExternPtr chain)
+{
+ ;
+}
+
+
+extern IK_Chain_ExternPtr IK_CreateChain(void)
+{
+ return 0;
+}
+
+
+
+/* texture.c */
+#define FLO 128
+#define INT 96
+ /* struct EnvMap; */
+ /* struct Tex; */
+void RE_free_envmap(struct EnvMap *env){}
+struct EnvMap *RE_copy_envmap(struct EnvMap *env){}
+void RE_free_envmapdata(struct EnvMap *env){}
+int RE_envmaptex(struct Tex *tex, float *texvec, float *dxt, float *dyt){}
+void RE_calc_R_ref(void){}
+char texstr[15][8]; /* buttons.c */
+Osa O;
+
+/* editsca.c */
+void make_unique_prop_names(char *str) {}
diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile
new file mode 100644
index 00000000000..08202dff9cc
--- /dev/null
+++ b/source/blender/blenkernel/intern/Makefile
@@ -0,0 +1,74 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+#
+
+LIBNAME = blenkernel
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd openbsd linux solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+# OpenGL and Python
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+# Reference to the types in makesdna and imbuf
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../imbuf
+# This mod uses the BLI and BLO module
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../bpython/include
+# also avi is used
+CPPFLAGS += -I../../avi
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# we still refer to /include a bit...
+CPPFLAGS += -I../../include
+
+# to include the render stuff:
+CPPFLAGS += -I../../render/extern/include
+
+# for sound
+#CPPFLAGS += -I../../../kernel/gen_system
+
+CPPFLAGS += -I$(NAN_IKSOLVER)/include
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
new file mode 100644
index 00000000000..9f5de3f34fa
--- /dev/null
+++ b/source/blender/blenkernel/intern/action.c
@@ -0,0 +1,873 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <math.h>
+#include <stdlib.h> /* for NULL */
+
+#include "MEM_guardedalloc.h"
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "BKE_action.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_utildefines.h"
+
+#include "DNA_object_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_action_types.h"
+#include "DNA_nla_types.h"
+
+#include "BKE_blender.h"
+#include "BKE_ipo.h"
+#include "BKE_object.h"
+#include "BKE_library.h"
+#include "BKE_anim.h"
+#include "BKE_armature.h"
+
+#include "nla.h"
+
+#include "BKE_constraint.h"
+#include "DNA_constraint_types.h"
+
+/* Local function prototypes */
+static
+ void
+do_pose_constraint_channels(
+ bPose *pose,
+ bAction *act,
+ float ctime
+);
+
+static
+ void
+get_constraint_influence_from_pose (
+ bPose *dst,
+ bPose *src
+);
+
+static
+ void
+blend_constraints(
+ ListBase *dst,
+ const ListBase *src,
+ float srcweight,
+ short mode
+);
+
+static
+ void
+rest_pose (
+ bPose *pose,
+ int clearflag
+);
+
+/* Implementation */
+
+ bPoseChannel *
+get_pose_channel (
+ const bPose *pose,
+ const char *name
+){
+ bPoseChannel *chan;
+
+ for (chan=pose->chanbase.first; chan; chan=chan->next){
+ if (!strcmp (chan->name, name))
+ return chan;
+ }
+
+ return NULL;
+}
+
+static
+ void
+rest_pose (
+ bPose *pose,
+ int clearflag
+){
+ bPoseChannel *chan;
+ int i;
+
+ if (!pose)
+ return;
+
+ for (chan=pose->chanbase.first; chan; chan=chan->next){
+ for (i=0; i<3; i++){
+ chan->loc[i]=0.0;
+ chan->quat[i+1]=0.0;
+ chan->size[i]=1.0;
+ }
+ chan->quat[0]=1.0;
+ if (clearflag)
+ chan->flag =0;
+ }
+}
+
+static
+ void
+blend_constraints(
+ ListBase *dst,
+ const ListBase *src,
+ float srcweight,
+ short mode
+){
+ bConstraint *dcon;
+ const bConstraint *scon;
+ float dstweight;
+
+ switch (mode){
+ case POSE_BLEND:
+ dstweight = 1.0F - srcweight;
+ break;
+ case POSE_ADD:
+ dstweight = 1.0F;
+ break;
+ }
+
+ /* Blend constraints */
+ for (dcon=dst->first; dcon; dcon=dcon->next){
+ for (scon = src->first; scon; scon=scon->next){
+ if (!strcmp(scon->name, dcon->name))
+ break;
+ }
+
+ if (scon){
+ dcon->enforce = (dcon->enforce*dstweight) + (scon->enforce*srcweight);
+ if (mode == POSE_BLEND)
+ dcon->enforce/=2.0;
+
+ if (dcon->enforce>1.0)
+ dcon->enforce=1.0;
+ if (dcon->enforce<0.0)
+ dcon->enforce=0.0;
+
+ }
+ }
+}
+
+ void
+blend_poses (
+ bPose *dst,
+ const bPose *src,
+ float srcweight,
+ short mode
+){
+ bPoseChannel *dchan;
+ const bPoseChannel *schan;
+ float dquat[4], squat[4], mat[3][3];
+ float dstweight;
+ int i;
+
+ switch (mode){
+ case POSE_BLEND:
+ dstweight = 1.0F - srcweight;
+ break;
+ case POSE_ADD:
+ dstweight = 1.0F;
+ break;
+ default :
+ dstweight = 1.0F;
+ }
+
+ for (dchan = dst->chanbase.first; dchan; dchan=dchan->next){
+ schan = get_pose_channel(src, dchan->name);
+ if (schan){
+ if (schan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)){
+
+ /* Convert both quats to matrices and then back again.
+ * This prevents interpolation problems
+ * This sucks because it is slow and stupid
+ */
+
+ QuatToMat3(dchan->quat, mat);
+ Mat3ToQuat(mat, dquat);
+ QuatToMat3(schan->quat, mat);
+ Mat3ToQuat(mat, squat);
+
+ /* Do the transformation blend */
+ for (i=0; i<3; i++){
+ if (schan->flag & POSE_LOC)
+ dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight);
+ if (schan->flag & POSE_SIZE)
+ dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight);
+ if (schan->flag & POSE_ROT)
+ dchan->quat[i+1] = (dquat[i+1]*dstweight) + (squat[i+1]*srcweight);
+ }
+
+ /* Do one more iteration for the quaternions only and normalize the quaternion if needed */
+ if (schan->flag & POSE_ROT)
+ dchan->quat[0] = 1.0f + ((dquat[0]-1.0f)*dstweight) + ((squat[0]-1.0f)*srcweight);
+ if (mode==POSE_BLEND)
+ NormalQuat (dchan->quat);
+ dchan->flag |= schan->flag;
+ }
+ }
+ }
+}
+
+ void
+clear_pose_constraint_status (
+ Object *ob
+){
+ bPoseChannel *chan;
+
+ if (!ob)
+ return;
+ if (!ob->pose)
+ return;
+
+ for (chan = ob->pose->chanbase.first; chan; chan=chan->next){
+ chan->flag &= ~PCHAN_DONE;
+ }
+}
+
+ float
+calc_action_start (
+ const bAction *act
+){
+ const bActionChannel *chan;
+ const IpoCurve *icu;
+ float size=999999999.0f;
+ int i;
+ int foundvert=0;
+ const bConstraintChannel *conchan;
+
+
+ if (!act)
+ return 0;
+
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ for (icu=chan->ipo->curve.first; icu; icu=icu->next)
+ for (i=0; i<icu->totvert; i++){
+ size = MIN2 (size, icu->bezt[i].vec[1][0]);
+ foundvert=1;
+
+ }
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
+ for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
+ for (i=0; i<icu->totvert; i++){
+ size = MIN2 (size, icu->bezt[i].vec[1][0]);
+ foundvert=1;
+ }
+ }
+ }
+
+ if (!foundvert)
+ return 0;
+ else
+ return size;
+}
+
+ float
+calc_action_end (
+ const bAction *act
+){
+ const bActionChannel *chan;
+ const bConstraintChannel *conchan;
+ const IpoCurve *icu;
+ float size=0;
+ int i;
+
+ if (!act)
+ return 0;
+
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ for (icu=chan->ipo->curve.first; icu; icu=icu->next)
+ for (i=0; i<icu->totvert; i++)
+ size = MAX2 (size, icu->bezt[i].vec[1][0]);
+
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
+ for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
+ for (i=0; i<icu->totvert; i++)
+ size = MAX2 (size, icu->bezt[i].vec[1][0]);
+ }
+ }
+ return size;
+}
+
+ void
+verify_pose_channel (
+ bPose* pose,
+ const char* name
+) {
+ bPoseChannel *chan;
+
+ if (!pose){
+ return;
+ }
+
+ /* See if this channel exists */
+ for (chan=pose->chanbase.first; chan; chan=chan->next){
+ if (!strcmp (name, chan->name))
+ return;
+ }
+
+ /* If not, create it and add it */
+ chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel");
+
+ strcpy (chan->name, name);
+ chan->loc[0] = chan->loc[1] = chan->loc[2] = 0.0F;
+ chan->quat[1] = chan->quat[2] = chan->quat[3] = 0.0F; chan->quat[0] = 1.0F;
+ chan->size[0] = chan->size[1] = chan->size[2] = 1.0F;
+
+ chan->flag |= POSE_ROT|POSE_SIZE|POSE_LOC;
+
+ BLI_addtail (&pose->chanbase, chan);
+}
+
+ void
+get_pose_from_pose (
+ bPose **pose,
+ const bPose *src
+){
+ const bPoseChannel *pchan;
+ bPoseChannel *newchan;
+
+ if (!src)
+ return;
+ if (!pose)
+ return;
+
+ /* If there is no pose, create one */
+ if (!*pose){
+ *pose=MEM_callocN (sizeof(bPose), "pose");
+ }
+
+ /* Copy the data from the action into the pose */
+ for (pchan=src->chanbase.first; pchan; pchan=pchan->next){
+ newchan = copy_pose_channel(pchan);
+ verify_pose_channel(*pose, pchan->name);
+ set_pose_channel(*pose, newchan);
+ }
+}
+
+static void get_constraint_influence_from_pose (bPose *dst, bPose *src)
+{
+ bConstraint *dcon, *scon;
+
+ if (!src || !dst)
+ return;
+
+ for (dcon = dst->chanbase.first; dcon; dcon=dcon->next){
+ for (scon=src->chanbase.first; scon; scon=scon->next){
+ if (!strcmp(scon->name, dcon->name))
+ break;
+ }
+ if (scon){
+ dcon->enforce = scon->enforce;
+ }
+ }
+}
+
+/* If the pose does not exist, a new one is created */
+
+ void
+get_pose_from_action (
+ bPose **pose,
+ bAction *act,
+ float ctime
+) {
+ bActionChannel *achan;
+ bPoseChannel *pchan;
+ Ipo *ipo;
+ IpoCurve *curve;
+
+
+ if (!act)
+ return;
+ if (!pose)
+ return;
+
+ /* If there is no pose, create one */
+ if (!*pose){
+ *pose=MEM_callocN (sizeof(bPose), "pose");
+ }
+
+ /* Copy the data from the action into the pose */
+ for (achan=act->chanbase.first; achan; achan=achan->next){
+ act->achan= achan;
+
+ ipo = achan->ipo;
+ if (ipo){
+ pchan=MEM_callocN (sizeof(bPoseChannel), "gpfa_poseChannel");
+ strcpy (pchan->name, achan->name);
+
+ act->pchan=pchan;
+ /* Evaluates and sets the internal ipo value */
+ calc_ipo(ipo, ctime);
+
+ /* Set the pchan flags */
+ for (curve = achan->ipo->curve.first; curve; curve=curve->next){
+ /* Skip empty curves */
+ if (!curve->totvert)
+ continue;
+
+ switch (curve->adrcode){
+ case AC_QUAT_X:
+ case AC_QUAT_Y:
+ case AC_QUAT_Z:
+ case AC_QUAT_W:
+ pchan->flag |= POSE_ROT;
+ break;
+ case AC_LOC_X:
+ case AC_LOC_Y:
+ case AC_LOC_Z:
+ pchan->flag |= POSE_LOC;
+ break;
+ case AC_SIZE_X:
+ case AC_SIZE_Y:
+ case AC_SIZE_Z:
+ pchan->flag |= POSE_SIZE;
+ break;
+ }
+ }
+
+ execute_ipo((ID*)act, achan->ipo);
+
+ set_pose_channel(*pose, pchan);
+ }
+ }
+}
+
+ void
+do_all_actions(
+){
+ Base *base;
+ bPose *apose=NULL;
+ bPose *tpose=NULL;
+ Object *ob;
+ bActionStrip *strip;
+ int doit;
+ float striptime, frametime, length, actlength;
+ float blendfac, stripframe;
+
+ int set;
+
+ /* NEW: current scene ob ipo's */
+ base= G.scene->base.first;
+ set= 0;
+
+ while(base) {
+
+ ob = base->object;
+
+ /* Retrieve data from the NLA */
+ if(ob->type==OB_ARMATURE){
+
+ doit=0;
+
+ /* Clear pose */
+ if (apose){
+ clear_pose(apose);
+ MEM_freeN(apose);
+ }
+ /* Clear pose */
+ if (tpose){
+ clear_pose(tpose);
+ MEM_freeN(tpose);
+ }
+
+ copy_pose(&apose, ob->pose, 1);
+ copy_pose(&tpose, ob->pose, 1);
+ rest_pose(apose, 1);
+
+ if (base->object->nlastrips.first){
+ rest_pose(base->object->pose, 0);
+ }
+
+ for (strip=base->object->nlastrips.first; strip; strip=strip->next){
+ doit = 0;
+ if (strip->act){
+
+ /* Determine if the current frame is within the strip's range */
+ length = strip->end-strip->start;
+ actlength = strip->actend-strip->actstart;
+ striptime = (G.scene->r.cfra-(strip->start)) / length;
+ stripframe = (G.scene->r.cfra-(strip->start)) ;
+
+
+ if (striptime>=0.0){
+
+ rest_pose(tpose, 1);
+
+ /* Handle path */
+ if (strip->flag & ACTSTRIP_USESTRIDE){
+ if (ob->parent && ob->parent->type==OB_CURVE){
+ Curve *cu = ob->parent->data;
+ float ctime, pdist;
+
+ if (cu->flag & CU_PATH){
+ /* Ensure we have a valid path */
+ if(cu->path==0 || cu->path->data==0) calc_curvepath(ob->parent);
+
+ /* Find the position on the path */
+ ctime= bsystem_time(ob, ob->parent, (float)G.scene->r.cfra, 0.0);
+
+ if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) {
+ ctime /= cu->pathlen;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+ pdist = ctime*cu->path->totdist;
+
+ if (strip->stridelen)
+ striptime = pdist / strip->stridelen;
+ else
+ striptime = 0;
+
+ striptime = (float)fmod (striptime, 1.0);
+
+ frametime = (striptime * actlength) + strip->actstart;
+ get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+#ifdef __NLA_BLENDCON
+ do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+#endif
+ doit=1;
+ }
+ }
+ }
+
+ /* Handle repeat */
+
+ else if (striptime < 1.0){
+ /* Mod to repeat */
+ striptime*=strip->repeat;
+ striptime = (float)fmod (striptime, 1.0);
+
+ frametime = (striptime * actlength) + strip->actstart;
+ get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+#ifdef __NLA_BLENDCON
+ do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+#endif
+ doit=1;
+ }
+ /* Handle extend */
+ else{
+ if (strip->flag & ACTSTRIP_HOLDLASTFRAME){
+ striptime = 1.0;
+ frametime = (striptime * actlength) + strip->actstart;
+ get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+#ifdef __NLA_BLENDCON
+ do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+#endif
+ doit=1;
+ }
+ }
+
+ /* Handle blendin & blendout */
+ if (doit){
+ /* Handle blendin */
+
+ if (strip->blendin>0.0 && stripframe<=strip->blendin && G.scene->r.cfra>=strip->start){
+ blendfac = stripframe/strip->blendin;
+ }
+ else if (strip->blendout>0.0 && stripframe>=(length-strip->blendout) && G.scene->r.cfra<=strip->end){
+ blendfac = (length-stripframe)/(strip->blendout);
+ }
+ else
+ blendfac = 1;
+
+ /* Blend this pose with the accumulated pose */
+ blend_poses (apose, tpose, blendfac, strip->mode);
+#ifdef __NLA_BLENDCON
+ blend_constraints(&apose->chanbase, &tpose->chanbase, blendfac, strip->mode);
+#endif
+ }
+ }
+ if (apose){
+ get_pose_from_pose(&ob->pose, apose);
+#ifdef __NLA_BLENDCON
+ get_constraint_influence_from_pose(ob->pose, apose);
+#endif
+ }
+ }
+
+ }
+
+ /* Do local action (always overrides the nla actions) */
+ /* At the moment, only constraint ipos on the local action have any effect */
+ if(base->object->action) {
+ get_pose_from_action (&ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0));
+ do_pose_constraint_channels(ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0));
+ doit = 1;
+ }
+
+ if (doit)
+ apply_pose_armature(get_armature(ob), ob->pose, 1);
+
+ }
+ base= base->next;
+ if(base==0 && set==0 && G.scene->set) {
+ set= 1;
+ base= G.scene->set->base.first;
+ }
+
+ }
+
+ if (apose){
+ clear_pose(apose);
+ MEM_freeN(apose);
+ apose = NULL;
+ }
+ if (tpose){
+ clear_pose(tpose);
+ MEM_freeN(tpose);
+ apose = NULL;
+ }
+
+}
+
+static void do_pose_constraint_channels(bPose *pose, bAction *act, float ctime)
+{
+ bPoseChannel *pchan;
+ bActionChannel *achan;
+
+ if (!pose || !act)
+ return;
+
+ for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
+ achan=get_named_actionchannel(act, pchan->name);
+ if (achan)
+ do_constraint_channels(&pchan->constraints, &achan->constraintChannels, ctime);
+ }
+}
+
+ bActionChannel *
+get_named_actionchannel (
+ bAction *act,
+ const char *name
+){
+ bActionChannel *chan;
+
+ if (!act)
+ return NULL;
+
+ for (chan = act->chanbase.first; chan; chan=chan->next){
+ if (!strcmp (chan->name, name))
+ return chan;
+ }
+
+ return NULL;
+}
+
+ void
+clear_pose (
+ bPose *pose
+) {
+ bPoseChannel *chan;
+
+ if (pose->chanbase.first){
+ for (chan = pose->chanbase.first; chan; chan=chan->next){
+ free_constraints(&chan->constraints);
+ }
+ BLI_freelistN (&pose->chanbase);
+ }
+}
+
+ void
+make_local_action(
+ bAction *act
+){
+ Object *ob;
+ bAction *actn;
+ int local=0, lib=0;
+
+ if(act->id.lib==0) return;
+ if(act->id.us==1) {
+ act->id.lib= 0;
+ act->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)act, 0);
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->action==act) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ act->id.lib= 0;
+ act->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)act, 0);
+ }
+ else if(local && lib) {
+ actn= copy_action(act);
+ actn->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->action==act) {
+
+ if(ob->id.lib==0) {
+ ob->action = actn;
+ ob->activecon = NULL;
+ actn->id.us++;
+ act->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+
+ void
+free_action(
+ bAction *act
+){
+ bActionChannel *chan;
+
+ /* Free channels */
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ if (chan->ipo)
+ chan->ipo->id.us--;
+ free_constraint_channels(&chan->constraintChannels);
+ }
+
+ if (act->chanbase.first)
+ BLI_freelistN (&act->chanbase);
+}
+
+ bAction*
+copy_action (
+ const bAction *src
+){
+ bAction *dst = NULL;
+ bActionChannel *dchan, *schan;
+
+ if(!src) return NULL;
+
+ dst= copy_libblock(src);
+ duplicatelist(&(dst->chanbase), &(src->chanbase));
+
+ for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next){
+ dchan->ipo = copy_ipo(dchan->ipo);
+ copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels);
+ }
+ dst->id.flag |= LIB_FAKEUSER;
+ dst->id.us++;
+ return dst;
+}
+
+ bPoseChannel *
+copy_pose_channel (
+ const bPoseChannel* src
+){
+ bPoseChannel *dst;
+
+ if (!src)
+ return NULL;
+
+ dst = MEM_callocN (sizeof(bPoseChannel), "copyPoseChannel");
+ memcpy (dst, src, sizeof(bPoseChannel));
+ dst->prev=dst->next=NULL;
+
+ return dst;
+}
+
+ void
+copy_pose(
+ bPose **dst,
+ const bPose *src,
+ int copycon
+){
+ bPose *outPose;
+ const bPose * inPose;
+ bPoseChannel *newChan;
+ const bPoseChannel *curChan;
+
+ inPose = src;
+
+ if (!inPose){
+ *dst=NULL;
+ return;
+ }
+
+ outPose=MEM_callocN(sizeof(bPose), "pose");
+
+ for (curChan=inPose->chanbase.first; curChan; curChan=curChan->next){
+ newChan=MEM_callocN(sizeof(bPoseChannel), "copyposePoseChannel");
+
+ strcpy (newChan->name, curChan->name);
+ newChan->flag=curChan->flag;
+
+ memcpy (newChan->loc, curChan->loc, sizeof (curChan->loc));
+ memcpy (newChan->size, curChan->size, sizeof (curChan->size));
+ memcpy (newChan->quat, curChan->quat, sizeof (curChan->quat));
+ Mat4CpyMat4 (newChan->obmat, curChan->obmat);
+
+ BLI_addtail (&outPose->chanbase, newChan);
+ if (copycon){
+ copy_constraints(&newChan->constraints, &curChan->constraints);
+ }
+ }
+
+ *dst=outPose;
+}
+
+bPoseChannel *set_pose_channel (bPose *pose, bPoseChannel *chan){
+ /* chan is no longer valid for the calling function.
+ and should not be used by that function after calling
+ this one
+ */
+ bPoseChannel *curChan;
+
+ /* Determine if an equivalent channel exists already */
+ for (curChan=pose->chanbase.first; curChan; curChan=curChan->next){
+ if (!strcmp (curChan->name, chan->name)){
+ if (chan->flag & POSE_ROT)
+ memcpy (curChan->quat, chan->quat, sizeof(chan->quat));
+ if (chan->flag & POSE_SIZE)
+ memcpy (curChan->size, chan->size, sizeof(chan->size));
+ if (chan->flag & POSE_LOC)
+ memcpy (curChan->loc, chan->loc, sizeof(chan->loc));
+ if (chan->flag & PCHAN_DONE)
+ Mat4CpyMat4 (curChan->obmat, chan->obmat);
+
+ curChan->flag |= chan->flag;
+ MEM_freeN (chan);
+ return curChan;
+ }
+ }
+
+ MEM_freeN (chan);
+ return NULL;
+ /* If an equivalent channel doesn't exist, then don't bother setting it. */
+}
+
+
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
new file mode 100644
index 00000000000..0fa358b30a0
--- /dev/null
+++ b/source/blender/blenkernel/intern/anim.c
@@ -0,0 +1,512 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "DNA_listBase.h"
+
+#include "DNA_object_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+#include "BKE_anim.h"
+#include "BKE_ipo.h"
+#include "BKE_object.h"
+#include "BKE_displist.h"
+#include "BKE_key.h"
+#include "BKE_font.h"
+#include "BKE_effect.h"
+
+#include "BKE_bad_level_calls.h"
+
+ListBase duplilist= {0, 0};
+
+void free_path(Path *path)
+{
+ if(path->data) MEM_freeN(path->data);
+ MEM_freeN(path);
+}
+
+
+void calc_curvepath(Object *ob)
+{
+ BevList *bl;
+ BevPoint *bevp, *bevpn, *bevpfirst, *bevplast;
+ Curve *cu;
+ Nurb *nu;
+ Path *path;
+ float *fp, *dist, *maxdist, x, y, z;
+ float fac, d=0, fac1, fac2;
+ int a, tot, cycl=0;
+ float *ft;
+
+ /* in een pad zitten allemaal punten met gelijke afstand: path->len = aantal pt */
+ /* NU MET BEVELCURVE!!! */
+
+ if(ob==0 || ob->type != OB_CURVE) return;
+ cu= ob->data;
+ if(ob==G.obedit) nu= editNurb.first;
+ else nu= cu->nurb.first;
+
+ if(cu->path) free_path(cu->path);
+ cu->path= 0;
+
+ if((cu->flag & CU_PATH)==0) return;
+
+ bl= cu->bev.first;
+ if(bl==0) {
+ makeDispList(ob);
+ bl= cu->bev.first;
+ }
+ if(bl==0) return;
+
+ cu->path=path= MEM_callocN(sizeof(Path), "path");
+
+ /* als POLY: laatste punt != eerste punt */
+ cycl= (bl->poly!= -1);
+
+ if(cycl) tot= bl->nr;
+ else tot= bl->nr-1;
+
+ path->len= tot+1;
+ /* exception: vector handle paths and polygon paths should be subdivided at least a factor 6 (or more?) */
+ if(path->len<6*nu->pntsu) path->len= 6*nu->pntsu;
+
+ dist= (float *)MEM_mallocN((tot+1)*4, "berekenpaddist");
+
+ /* alle lengtes in *dist */
+ bevp= bevpfirst= (BevPoint *)(bl+1);
+ fp= dist;
+ *fp= 0;
+ for(a=0; a<tot; a++) {
+ fp++;
+ if(cycl && a==tot-1) {
+ x= bevpfirst->x - bevp->x;
+ y= bevpfirst->y - bevp->y;
+ z= bevpfirst->z - bevp->z;
+ }
+ else {
+ x= (bevp+1)->x - bevp->x;
+ y= (bevp+1)->y - bevp->y;
+ z= (bevp+1)->z - bevp->z;
+ }
+ *fp= *(fp-1)+ (float)sqrt(x*x+y*y+z*z);
+
+ bevp++;
+ }
+
+ path->totdist= *fp;
+
+ /* de padpunten in path->data */
+ /* nu ook met TILT */
+ ft= path->data = (float *)MEM_callocN(16*path->len, "pathdata");
+
+ bevp= bevpfirst;
+ bevpn= bevp+1;
+ bevplast= bevpfirst + (bl->nr-1);
+ fp= dist+1;
+ maxdist= dist+tot;
+ fac= 1.0f/((float)path->len-1.0f);
+
+ for(a=0; a<path->len; a++) {
+
+ d= ((float)a)*fac*path->totdist;
+
+ /* we zoeken plek 'd' in het array */
+ while((d>= *fp) && fp<maxdist) {
+ fp++;
+ if(bevp<bevplast) bevp++;
+ bevpn= bevp+1;
+ if(bevpn>bevplast) {
+ if(cycl) bevpn= bevpfirst;
+ else bevpn= bevplast;
+ }
+ }
+
+ fac1= *(fp)- *(fp-1);
+ fac2= *(fp)-d;
+ fac1= fac2/fac1;
+ fac2= 1.0f-fac1;
+
+ ft[0]= fac1*bevp->x+ fac2*(bevpn)->x;
+ ft[1]= fac1*bevp->y+ fac2*(bevpn)->y;
+ ft[2]= fac1*bevp->z+ fac2*(bevpn)->z;
+ ft[3]= fac1*bevp->alfa+ fac2*(bevpn)->alfa;
+
+ ft+= 4;
+
+ }
+
+ MEM_freeN(dist);
+}
+
+int interval_test(int min, int max, int p1, int cycl)
+{
+
+ if(cycl) {
+ if( p1 < min)
+ p1= ((p1 -min) % (max-min+1)) + max+1;
+ else if(p1 > max)
+ p1= ((p1 -min) % (max-min+1)) + min;
+ }
+ else {
+ if(p1 < min) p1= min;
+ else if(p1 > max) p1= max;
+ }
+ return p1;
+}
+
+int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* geeft OK terug */
+{
+ Curve *cu;
+ Nurb *nu;
+ BevList *bl;
+ Path *path;
+ float *fp, *p0, *p1, *p2, *p3, fac;
+ float data[4];
+ int cycl=0, s0, s1, s2, s3;
+
+
+ if(ob==0 || ob->type != OB_CURVE) return 0;
+ cu= ob->data;
+ if(cu->path==0 || cu->path->data==0) calc_curvepath(ob);
+ path= cu->path;
+ fp= path->data;
+
+ /* cyclic testen */
+ bl= cu->bev.first;
+ if(bl && bl->poly> -1) cycl= 1;
+
+ /* ctime is van 0.0-1.0 */
+ ctime *= (path->len-1);
+
+ s1= (int)floor(ctime);
+ fac= (float)(s1+1)-ctime;
+
+ /* path->len is gecorrigeerd voor cyclic, zie boven, is beetje warrig! */
+ 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= fp + 4*s0;
+ p1= fp + 4*s1;
+ p2= fp + 4*s2;
+ p3= fp + 4*s3;
+
+ if(cu->flag & CU_FOLLOW) {
+
+ set_afgeleide_four_ipo(1.0f-fac, data, KEY_BSPLINE);
+
+ dir[0]= data[0]*p0[0] + data[1]*p1[0] + data[2]*p2[0] + data[3]*p3[0] ;
+ dir[1]= data[0]*p0[1] + data[1]*p1[1] + data[2]*p2[1] + data[3]*p3[1] ;
+ dir[2]= data[0]*p0[2] + data[1]*p1[2] + data[2]*p2[2] + data[3]*p3[2] ;
+
+ /* compatible maken met vectoquat */
+ dir[0]= -dir[0];
+ dir[1]= -dir[1];
+ dir[2]= -dir[2];
+ }
+
+ nu= cu->nurb.first;
+
+ /* zeker van zijn dat de eerste en laatste frame door de punten gaat */
+ if((nu->type & 7)==CU_POLY) set_four_ipo(1.0f-fac, data, KEY_LINEAR);
+ else if((nu->type & 7)==CU_BEZIER) set_four_ipo(1.0f-fac, data, KEY_LINEAR);
+ else if(s0==s1 || p2==p3) set_four_ipo(1.0f-fac, data, KEY_CARDINAL);
+ else set_four_ipo(1.0f-fac, data, KEY_BSPLINE);
+
+ vec[0]= data[0]*p0[0] + data[1]*p1[0] + data[2]*p2[0] + data[3]*p3[0] ;
+ vec[1]= data[0]*p0[1] + data[1]*p1[1] + data[2]*p2[1] + data[3]*p3[1] ;
+ vec[2]= data[0]*p0[2] + data[1]*p1[2] + data[2]*p2[2] + data[3]*p3[2] ;
+
+ vec[3]= data[0]*p0[3] + data[1]*p1[3] + data[2]*p2[3] + data[3]*p3[3] ;
+
+ return 1;
+}
+
+void frames_duplilist(Object *ob)
+{
+ extern int enable_cu_speed; /* object.c */
+ Object *newob;
+ int cfrao, ok;
+
+ cfrao= G.scene->r.cfra;
+ if(ob->parent==0 && ob->track==0 && ob->ipo==0) return;
+
+ if(ob->transflag & OB_DUPLINOSPEED) enable_cu_speed= 0;
+
+ /* dit om zeker van te zijn dat er iets gezbufferd wordt: in drawobject.c: dt==wire en boundboxclip */
+ if(G.background==0 && ob->type==OB_MESH) {
+ Mesh *me= ob->data;
+ DispList *dl;
+ if(me->disp.first==0) addnormalsDispList(ob, &me->disp);
+ if(ob->dt==OB_SHADED) {
+ dl= ob->disp.first;
+ if(dl==0 || dl->col1==0) shadeDispList(ob);
+ }
+ }
+
+ for(G.scene->r.cfra= ob->dupsta; G.scene->r.cfra<=ob->dupend; G.scene->r.cfra++) {
+
+ ok= 1;
+ if(ob->dupoff) {
+ ok= G.scene->r.cfra - ob->dupsta;
+ ok= ok % (ob->dupon+ob->dupoff);
+ if(ok < ob->dupon) ok= 1;
+ else ok= 0;
+ }
+ if(ok) {
+ newob= MEM_mallocN(sizeof(Object), "newobobj dupli");
+ memcpy(newob, ob, sizeof(Object));
+
+ /* alleen de basis-ball behoeft een displist */
+ if(newob->type==OB_MBALL) newob->disp.first= newob->disp.last= 0;
+
+ BLI_addtail(&duplilist, newob);
+ do_ob_ipo(newob);
+ where_is_object(newob);
+
+ newob->flag |= OB_FROMDUPLI;
+ newob->id.newid= (ID *)ob; /* duplicator bewaren */
+ }
+ }
+
+ G.scene->r.cfra= cfrao;
+ enable_cu_speed= 1;
+ do_ob_ipo(ob);
+}
+
+
+void vertex_duplilist(Scene *sce, Object *par)
+{
+ Object *ob, *newob;
+ Base *base;
+ MVert *mvert;
+ Mesh *me;
+ float vec[3], pvec[3], pmat[4][4], mat[3][3], tmat[4][4];
+ float *q2;
+ int lay, totvert, a;
+
+ Mat4CpyMat4(pmat, par->obmat);
+
+ Mat4One(tmat);
+
+ lay= G.scene->lay;
+
+ base= sce->base.first;
+ while(base) {
+
+ if(base->object->type>0 && (lay & base->lay) && G.obedit!=base->object) {
+ ob= base->object->parent;
+ while(ob) {
+ if(ob==par) {
+
+ ob= base->object;
+ /* mballs have a different dupli handling */
+ if(ob->type!=OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */
+
+ me= par->data;
+ mvert= me->mvert;
+ mvert+= (me->totvert-1);
+ VECCOPY(pvec, mvert->co);
+ Mat4MulVecfl(pmat, pvec);
+
+ mvert= me->mvert;
+ totvert= me->totvert;
+
+ for(a=0; a<totvert; a++, mvert++) {
+
+ /* bereken de extra offset (tov. nulpunt parent) die de kinderen krijgen */
+ VECCOPY(vec, mvert->co);
+ Mat4MulVecfl(pmat, vec);
+ VecSubf(vec, vec, pmat[3]);
+ VecAddf(vec, vec, ob->obmat[3]);
+
+ newob= MEM_mallocN(sizeof(Object), "newobj dupli");
+ memcpy(newob, ob, sizeof(Object));
+ newob->flag |= OB_FROMDUPLI;
+ newob->id.newid= (ID *)par; /* duplicator bewaren */
+
+ /* alleen de basis-ball behoeft een displist */
+ if(newob->type==OB_MBALL) newob->disp.first= newob->disp.last= 0;
+
+ VECCOPY(newob->obmat[3], vec);
+
+ if(par->transflag & OB_DUPLIROT) {
+ VECCOPY(vec, mvert->no);
+ vec[0]= -vec[0]; vec[1]= -vec[1]; vec[2]= -vec[2];
+
+ q2= vectoquat(vec, ob->trackflag, ob->upflag);
+
+ QuatToMat3(q2, mat);
+ Mat4CpyMat4(tmat, newob->obmat);
+ Mat4MulMat43(newob->obmat, tmat, mat);
+ }
+
+ newob->parent= 0;
+ newob->track= 0;
+ /* newob->borig= base; */
+
+ BLI_addtail(&duplilist, newob);
+
+ VECCOPY(pvec, vec);
+
+ }
+ break;
+ }
+ ob= ob->parent;
+ }
+ }
+ base= base->next;
+ }
+}
+
+
+void particle_duplilist(Scene *sce, Object *par, PartEff *paf)
+{
+ Object *ob, *newob;
+ Base *base;
+ Particle *pa;
+ float ctime, vec1[3];
+ float vec[3], tmat[4][4], mat[3][3];
+ float *q2;
+ int lay, a;
+
+ pa= paf->keys;
+ if(pa==0) {
+ build_particle_system(par);
+ pa= paf->keys;
+ if(pa==0) return;
+ }
+
+ ctime= bsystem_time(par, 0, (float)G.scene->r.cfra, 0.0);
+
+ lay= G.scene->lay;
+
+ base= sce->base.first;
+ while(base) {
+
+ if(base->object->type>0 && (base->lay & lay) && G.obedit!=base->object) {
+ ob= base->object->parent;
+ while(ob) {
+ if(ob==par) {
+
+ ob= base->object;
+
+ pa= paf->keys;
+ for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
+
+ if(ctime > pa->time) {
+ if(ctime < pa->time+pa->lifetime) {
+
+ newob= MEM_mallocN(sizeof(Object), "newobj dupli");
+ memcpy(newob, ob, sizeof(Object));
+ newob->flag |= OB_FROMDUPLI;
+ newob->id.newid= (ID *)par; /* duplicator bewaren */
+
+ /* alleen de basis-ball behoeft een displist */
+ if(newob->type==OB_MBALL) newob->disp.first= newob->disp.last= 0;
+
+ where_is_particle(paf, pa, ctime, vec);
+ if(paf->stype==PAF_VECT) {
+ where_is_particle(paf, pa, ctime+1.0f, vec1);
+
+ VecSubf(vec1, vec1, vec);
+ q2= vectoquat(vec1, ob->trackflag, ob->upflag);
+
+ QuatToMat3(q2, mat);
+ Mat4CpyMat4(tmat, newob->obmat);
+ Mat4MulMat43(newob->obmat, tmat, mat);
+ }
+
+ VECCOPY(newob->obmat[3], vec);
+
+ newob->parent= 0;
+ newob->track= 0;
+
+ BLI_addtail(&duplilist, newob);
+
+ }
+ }
+ }
+ break;
+ }
+ ob= ob->parent;
+ }
+ }
+ base= base->next;
+ }
+}
+
+
+void free_duplilist()
+{
+ Object *ob;
+
+ while( ob= duplilist.first) {
+ BLI_remlink(&duplilist, ob);
+ MEM_freeN(ob);
+ }
+
+}
+
+void make_duplilist(Scene *sce, Object *ob)
+{
+ PartEff *paf;
+
+ if(ob->transflag & OB_DUPLI) {
+ if(ob->transflag & OB_DUPLIVERTS) {
+ if(ob->type==OB_MESH) {
+ if(ob->transflag & OB_DUPLIVERTS) {
+ if( paf=give_parteff(ob) ) particle_duplilist(sce, ob, paf);
+ else vertex_duplilist(sce, ob);
+ }
+ }
+ else if(ob->type==OB_FONT) {
+ font_duplilist(ob);
+ }
+ }
+ else if(ob->transflag & OB_DUPLIFRAMES) frames_duplilist(ob);
+ }
+}
+
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
new file mode 100644
index 00000000000..86ce2faa07c
--- /dev/null
+++ b/source/blender/blenkernel/intern/armature.c
@@ -0,0 +1,1451 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include "MEM_guardedalloc.h"
+
+#include "nla.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_action_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_constraint_types.h"
+
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_library.h"
+#include "BKE_blender.h"
+#include "BKE_armature.h"
+#include "BKE_action.h"
+#include "BKE_constraint.h"
+#include "BKE_object.h"
+#include "BKE_object.h"
+#include "BKE_deform.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_editdeform.h"
+
+#include "IK_solver.h"
+
+/* Function prototypes */
+
+static void apply_pose_bonechildren (Bone* bone, bPose* pose, int doit);
+static float dist_to_bone (float vec[3], float b1[3], float b2[3]);
+static Bone *get_named_bone_bonechildren (Bone *bone, const char *name);
+static Bone *get_indexed_bone_bonechildren (Bone *bone, int *index);
+/*void make_bone_parent_matrix (Bone* bone);*/
+static void copy_bonechildren (Bone* newBone, Bone* oldBone);
+static void calc_armature_deform_bonechildren (Bone *bone, float *vec, float *co, float *contrib, float obmat[][4]);
+static int verify_boneptr_children (Bone *cBone, Bone *tBone);
+static void where_is_bonelist_time (Object *ob, ListBase *base, float ctime);
+static Bone *get_last_ik_bone (Bone *bone);
+static void precalc_bonelist_posemats(ListBase *bonelist, float parlen);
+
+/* Globals */
+static float g_premat[4][4];
+static float g_postmat[4][4];
+static MDeformVert *g_dverts;
+static ListBase *g_defbase;
+static bArmature *g_defarm;
+
+/* Functions */
+
+float get_bone_length (Bone *bone)
+{
+ float result[3];
+
+ VecSubf (result, bone->tail, bone->head);
+ return (float)sqrt(result[0]*result[0] + result[1]*result[1] + result[2]*result[2]);
+
+}
+
+void apply_bonemat(Bone *bone)
+{
+ float mat[3][3], imat[3][3], tmat[3][3];
+
+ if(!bone)
+ return;
+
+ Mat3CpyMat4(mat, bone->obmat);
+
+ VECCOPY(bone->loc, bone->obmat[3]);
+
+ Mat3ToQuat(mat, bone->quat);
+ QuatToMat3(bone->quat, tmat);
+
+ Mat3Inv(imat, tmat);
+
+ Mat3MulMat3(tmat, imat, mat);
+
+ bone->size[0]= tmat[0][0];
+ bone->size[1]= tmat[1][1];
+ bone->size[2]= tmat[2][2];
+
+}
+
+void GB_build_mats (float parmat[][4], float obmat[][4], float premat[][4], float postmat[][4])
+{
+ float obinv[4][4];
+#if 0
+ Mat4Invert(obinv, obmat);
+ Mat4CpyMat4(premat, obmat);
+ Mat4MulMat4(postmat, parmat, obinv);
+
+ Mat4Invert (postmat, premat);
+#else
+ Mat4Invert(obinv, obmat);
+ Mat4CpyMat4(premat, obmat);
+ Mat4MulMat4(postmat, parmat, obinv);
+
+ Mat4Invert (premat, postmat);
+#endif
+}
+
+void GB_init_armature_deform(ListBase *defbase, float premat[][4], float postmat[][4])
+{
+ g_defbase = defbase;
+ Mat4CpyMat4 (g_premat, premat);
+ Mat4CpyMat4 (g_postmat, postmat);
+
+}
+
+void GB_validate_defgroups (Mesh *mesh, ListBase *defbase)
+{
+ /* Should only be called when the mesh or armature changes */
+ int j, i;
+ MDeformVert *dvert;
+
+ for (j=0; j<mesh->totvert; j++){
+ dvert = mesh->dvert+j;
+ for (i=0; i<dvert->totweight; i++)
+ dvert->dw[i].data = ((bDeformGroup*)BLI_findlink (defbase, dvert->dw[i].def_nr))->data;
+ }
+}
+
+void GB_calc_armature_deform (float *co, MDeformVert *dvert)
+{
+ float vec[3]={0, 0, 0};
+ float contrib = 0;
+ int i;
+ Bone *bone;
+
+ Mat4MulVecfl(g_premat, co);
+
+ for (i=0; i<dvert->totweight; i++){
+ bone = dvert->dw[i].data;
+ if (bone) calc_bone_deform (bone, dvert->dw[i].weight, vec, co, &contrib);
+ }
+
+ if (contrib){
+ vec[0]/=contrib;
+ vec[1]/=contrib;
+ vec[2]/=contrib;
+ }
+
+ VecAddf (co, vec, co);
+ Mat4MulVecfl(g_postmat, co);
+}
+
+static Bone *get_last_ik_bone (Bone *bone)
+{
+ Bone *curBone;
+
+ for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
+ if (curBone->flag & BONE_IK_TOPARENT){
+ return get_last_ik_bone (curBone);
+ }
+ }
+
+ return bone;
+}
+
+#if 0
+static Bone *get_first_ik_bone (Bone *bone)
+{
+ Bone *curBone;
+
+ for (curBone = bone; curBone; curBone=curBone->parent){
+ if (!bone->parent)
+ return curBone;
+ if (!bone->flag & BONE_IK_TOPARENT)
+ return curBone;
+ }
+
+ return bone;
+/* for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
+ if (curBone->flag & BONE_IK_TOPARENT){
+ return get_last_ik_bone (curBone);
+ }
+ }
+*/
+ return bone;
+
+}
+#endif
+
+void where_is_bone(Object *ob, Bone *bone)
+{
+ where_is_bone_time (ob, bone, G.scene->r.cfra);
+}
+
+void where_is_bone_time (Object *ob, Bone *bone, float ctime)
+{
+ where_is_bone1_time (ob, get_last_ik_bone(bone), ctime);
+}
+
+void rebuild_bone_parent_matrix (Bone *bone)
+{
+ if (!bone)
+ return;
+
+ if (bone->parent)
+ rebuild_bone_parent_matrix(bone->parent);
+
+ /* Get the parent inverse */
+ if (bone->parent)
+ Mat4MulMat4(bone->parmat, bone->parent->obmat, bone->parent->parmat);
+ else
+ Mat4One (bone->parmat);
+
+}
+void where_is_bone1_time (Object *ob, Bone *bone, float ctime)
+/* Assumes the pose has already been retrieved from the action */
+/* Also assumes where_is_object has been called for owner */
+{
+ bPose *pose;
+ bPoseChannel *chan;
+ bArmature *arm;
+ float imat[4][4];
+ float totmat[4][4];
+ Object conOb;
+
+ pose = ob->pose;
+ if (!pose)
+ return;
+
+ arm = get_armature(ob);
+
+ /* Ensure there is achannel for this bone*/
+ verify_pose_channel (pose, bone->name);
+
+ /* Search the pose for a channel with the same name, and copy the
+ transformations from the channel into the bone */
+ for (chan=pose->chanbase.first; chan; chan=chan->next){
+ if (!strcmp (chan->name, bone->name)){
+
+#if 1 /* If 1 attempt to use pose caching features */
+ /* Bail out if we've been recalced recently */
+ if (chan->flag & PCHAN_DONE){
+ Mat4CpyMat4 (bone->obmat, chan->obmat);
+ if (bone->parent){
+ if ((bone->flag & BONE_IK_TOPARENT))
+ where_is_bone1_time (ob, bone->parent, ctime);
+ else
+ where_is_bone_time (ob, bone->parent, ctime);
+ }
+ return;
+ }
+ else
+ chan->flag |= PCHAN_DONE;
+#endif
+ break;
+ }
+ }
+
+#if 1
+ /* Ensure parents have been evaluated */
+ if (bone->parent){
+ if ((bone->flag & BONE_IK_TOPARENT))
+ where_is_bone1_time (ob, bone->parent, ctime);
+ else
+ where_is_bone_time (ob, bone->parent, ctime);
+ }
+
+ /* Build the parent matrix : Depreciated */
+// if (bone->parent)
+// Mat4MulMat4(bone->parmat, bone->parent->obmat, bone->parent->parmat);
+// else
+// Mat4One (bone->parmat);
+#endif
+
+ if (arm){
+ if ((arm->flag & ARM_RESTPOS) || ((G.obedit && (ob->data == G.obedit->data)))){
+ Mat4One (bone->obmat);
+ Mat4One (chan->obmat);
+ return;
+ }
+ }
+
+ if (bone->flag & BONE_IK_TOPARENT){
+ bone->loc[0]=bone->loc[1]=bone->loc[2]=0.0F;
+ }
+ bone_to_mat4(bone, bone->obmat);
+
+ /* Do constraints */
+ // clear_workob();
+
+ memset(&conOb, 0, sizeof(Object));
+ conOb.size[0]= conOb.size[1]= conOb.size[2]= 1.0;
+
+ /* Collect the constraints from the pose */
+ conOb.constraints.first = chan->constraints.first;
+ conOb.constraints.last = chan->constraints.last;
+
+ /* Totmat takes bone's obmat to worldspace */
+
+ {
+ float parmat[4][4];
+ float temp[4][4];
+
+ Mat4CpyMat4 (temp, bone->obmat);
+ Mat4One (bone->obmat);
+ get_objectspace_bone_matrix(bone, parmat, 1, 1);
+ Mat4CpyMat4 (bone->obmat, temp);
+ Mat4MulMat4 (totmat, parmat, ob->obmat);
+ }
+
+ /* Build a workob to pass the bone to the constraint solver */
+ conOb.data = ob->data;
+ conOb.type = ob->type;
+ conOb.parent = ob;
+ conOb.trackflag = ob->trackflag;
+ conOb.upflag = ob->upflag;
+
+ VECCOPY(conOb.size, bone->size);
+
+ Mat4MulMat4 (conOb.obmat, bone->obmat, totmat);
+
+ /* Solve */
+ solve_constraints (&conOb, TARGET_BONE, (void*)bone, ctime);
+
+ {
+ float parmat[4][4];
+ float temp[4][4];
+
+ Mat4CpyMat4 (temp, bone->obmat);
+ Mat4One (bone->obmat);
+ get_objectspace_bone_matrix(bone, parmat, 1, 1);
+ Mat4CpyMat4 (bone->obmat, temp);
+ Mat4MulMat4 (totmat, parmat, ob->obmat);
+ }
+
+ VECCOPY(bone->size, conOb.size);
+
+ /* Take out of worldspace */
+ Mat4Invert (imat, totmat);
+ Mat4MulMat4 (bone->obmat, conOb.obmat, imat);
+ Mat4CpyMat4 (chan->obmat, bone->obmat);
+
+}
+
+
+bArmature *get_armature(Object *ob)
+{
+ if(ob==NULL) return NULL;
+ if(ob->type==OB_ARMATURE) return ob->data;
+ else return NULL;
+}
+
+void init_armature_deform(Object *parent, Object *ob)
+{
+ bArmature *arm;
+ bDeformGroup *dg;
+ Bone *curBone;
+ MDeformVert *dvert;
+ int totverts;
+ float obinv[4][4];
+ int i, j;
+
+ arm = get_armature(parent);
+ if (!arm)
+ return;
+
+ if (ob)
+ where_is_object (ob);
+
+#if 1
+ apply_pose_armature (arm, parent->pose, 1); /* Hopefully doit parameter can be set to 0 in future */
+ where_is_armature (parent);
+#else
+ apply_pose_armature (arm, parent->pose, 0);
+#endif
+
+ g_defbase = &ob->defbase;
+ g_defarm = arm;
+
+ Mat4Invert(obinv, ob->obmat);
+ Mat4CpyMat4(g_premat, ob->obmat);
+ Mat4MulMat4(g_postmat, parent->obmat, obinv);
+
+ Mat4Invert (g_premat, g_postmat);
+
+ /* Store the deformation verts */
+ if (ob->type==OB_MESH){
+ g_dverts = ((Mesh*)ob->data)->dvert;
+ totverts = ((Mesh*)ob->data)->totvert;
+ }
+ else{
+ g_dverts=NULL;
+ totverts=0;
+ }
+
+ /* Precalc bone defmats */
+ precalc_armature_posemats (arm);
+
+ for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
+ precalc_bone_defmat(curBone);
+ }
+
+ /* Validate bone data in bDeformGroups */
+
+ for (dg=g_defbase->first; dg; dg=dg->next)
+ dg->data = (void*)get_named_bone(arm, dg->name);
+
+ if (g_dverts){
+ for (j=0; j<totverts; j++){
+ dvert = g_dverts+j;
+ for (i=0; i<dvert->totweight; i++){
+ bDeformGroup *fg;
+ fg = BLI_findlink (g_defbase, dvert->dw[i].def_nr);
+
+ if (fg)
+ dvert->dw[i].data = fg->data;
+ else
+ dvert->dw[i].data = NULL;
+ }
+ }
+ }
+}
+
+void get_bone_root_pos (Bone* bone, float vec[3], int posed)
+{
+ Bone *curBone;
+ float mat[4][4];
+
+ get_objectspace_bone_matrix(bone, mat, 1, posed);
+ VECCOPY (vec, mat[3]);
+ return;
+
+ rebuild_bone_parent_matrix(bone);
+ if (posed){
+
+ get_objectspace_bone_matrix(bone, mat, 1, posed);
+ VECCOPY (vec, mat[3]);
+ }
+ else {
+ vec[0]=vec[1]=vec[2]=0.0F;
+ for (curBone=bone; curBone; curBone=curBone->parent){
+ if (curBone==bone)
+ VecAddf (vec, vec, curBone->head);
+ else
+ VecAddf (vec, vec, curBone->tail);
+ }
+ }
+}
+
+void get_bone_tip_pos (Bone* bone, float vec[3], int posed)
+{
+ Bone *curBone;
+ float mat[4][4], tmat[4][4], rmat[4][4], bmat[4][4], fmat[4][4];
+
+ get_objectspace_bone_matrix(bone, mat, 0, posed);
+ VECCOPY (vec, mat[3]);
+ return;
+
+ rebuild_bone_parent_matrix(bone);
+ if (posed){
+
+ Mat4One (mat);
+
+ for (curBone = bone; curBone; curBone=curBone->parent){
+ Mat4One (bmat);
+ /* [BMAT] This bone's offset */
+ VECCOPY (bmat[3], curBone->head);
+ if (curBone==bone){
+ Mat4One (tmat);
+ VecSubf (tmat[3], curBone->tail, curBone->head);
+ Mat4MulMat4 (bmat, tmat, curBone->obmat);
+ VecAddf (bmat[3], bmat[3], curBone->head);
+ }
+ else
+ VecAddf (bmat[3], bmat[3], curBone->obmat[3]); // Test
+
+ /* [RMAT] Parent's bone length = parent rotmat * bone length */
+ if (curBone->parent){
+ Mat4One (tmat);
+ VecSubf (tmat[3], curBone->parent->tail, curBone->parent->head);
+ Mat4MulMat4 (rmat, tmat, curBone->parent->obmat);
+ VecSubf (rmat[3], rmat[3], curBone->parent->obmat[3]);
+ }
+ else
+ Mat4One (rmat);
+
+ Mat4MulSerie (fmat, rmat, bmat, mat, 0, 0, 0, 0, 0);
+ Mat4CpyMat4 (mat, fmat);
+ }
+
+ VECCOPY (vec, mat[3]);
+ }
+ else{
+ vec[0]=vec[1]=vec[2]=0.0F;
+ for (curBone=bone; curBone; curBone=curBone->parent){
+ VecAddf (vec, vec, curBone->tail);
+ }
+ }
+}
+
+int verify_boneptr (bArmature *arm, Bone *bone)
+{
+ /* Ensures that a given bone exists in an armature */
+ Bone *curBone;
+
+ if (!arm)
+ return 0;
+
+ for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
+ if (verify_boneptr_children (curBone, bone))
+ return 1;
+ }
+
+ return 0;
+}
+
+static int verify_boneptr_children (Bone *cBone, Bone *tBone)
+{
+ Bone *curBone;
+
+ if (cBone == tBone)
+ return 1;
+
+ for (curBone=cBone->childbase.first; curBone; curBone=curBone->next){
+ if (verify_boneptr_children (curBone, tBone))
+ return 1;
+ }
+ return 0;
+}
+
+
+static float dist_to_bone (float vec[3], float b1[3], float b2[3])
+{
+/* float dist=0; */
+ float bdelta[3];
+ float pdelta[3];
+ float hsqr, a, l;
+
+ VecSubf (bdelta, b2, b1);
+ l = Normalise (bdelta);
+
+ VecSubf (pdelta, vec, b1);
+
+ a = bdelta[0]*pdelta[0] + bdelta[1]*pdelta[1] + bdelta[2]*pdelta[2];
+ hsqr = ((pdelta[0]*pdelta[0]) + (pdelta[1]*pdelta[1]) + (pdelta[2]*pdelta[2]));
+
+ if (a < 0.0F){
+ //return 100000;
+ /* If we're past the end of the bone, do some weird field attenuation thing */
+ return ((b1[0]-vec[0])*(b1[0]-vec[0]) +(b1[1]-vec[1])*(b1[1]-vec[1]) +(b1[2]-vec[2])*(b1[2]-vec[2])) ;
+ }
+ else if (a > l){
+ //return 100000;
+ /* If we're past the end of the bone, do some weird field attenuation thing */
+ return ((b2[0]-vec[0])*(b2[0]-vec[0]) +(b2[1]-vec[1])*(b2[1]-vec[1]) +(b2[2]-vec[2])*(b2[2]-vec[2])) ;
+ }
+ else {
+ return (hsqr - (a*a));
+ }
+
+
+}
+
+static void calc_armature_deform_bonechildren (Bone *bone, float *vec, float *co, float *contrib, float obmat[][4])
+{
+ Bone *curBone;
+ float root[3];
+ float tip[3];
+ float dist, fac, ifac;
+ float cop[3];
+ float bdsqr;
+
+
+ get_bone_root_pos (bone, root, 0);
+ get_bone_tip_pos (bone, tip, 0);
+
+ bdsqr = bone->dist*bone->dist;
+ VECCOPY (cop, co);
+
+ dist = dist_to_bone(cop, root, tip);
+
+ if ((dist) <= bdsqr){
+ fac = (dist)/bdsqr;
+ ifac = 1.0F-fac;
+
+ ifac*=bone->weight;
+
+ if (!vec)
+ (*contrib) +=ifac;
+ else{
+ ifac*=(1.0F/(*contrib));
+
+ VECCOPY (cop, co);
+
+ Mat4MulVecfl(bone->defmat, cop);
+
+ VecSubf (cop, cop, co); // Make this a delta from the base position
+ cop[0]*=ifac; cop[1]*=ifac; cop[2]*=ifac;
+ VecAddf (vec, vec, cop);
+
+ }
+ }
+
+// calc_bone_deform (bone, bone->weight, vec, co, contrib, obmat);
+ for (curBone = bone->childbase.first; curBone; curBone=curBone->next)
+ calc_armature_deform_bonechildren (curBone, vec, co, contrib, obmat);
+}
+
+void precalc_bone_irestmat (Bone *bone)
+{
+ float restmat[4][4];
+
+ get_objectspace_bone_matrix(bone, restmat, 1, 0);
+ Mat4Invert (bone->irestmat, restmat);
+}
+
+static void precalc_bonelist_posemats(ListBase *bonelist, float parlen)
+{
+ Bone *curBone;
+ float length;
+ float T_parlen[4][4];
+ float T_root[4][4];
+ float M_obmat[4][4];
+ float R_bmat[4][4];
+ float M_accumulatedMatrix[4][4];
+ float delta[3];
+
+ for (curBone = bonelist->first; curBone; curBone=curBone->next){
+
+ /* Get the length translation (length along y axis) */
+ length = get_bone_length(curBone);
+
+ /* Get the bone's root offset (in the parent's coordinate system) */
+ Mat4One (T_root);
+ VECCOPY (T_root[3], curBone->head);
+
+ /* Compose the restmat */
+ VecSubf(delta, curBone->tail, curBone->head);
+ make_boneMatrixvr(R_bmat, delta, curBone->roll);
+
+ /* Retrieve the obmat (user transformation) */
+ Mat4CpyMat4 (M_obmat, curBone->obmat);
+
+ /* Compose the accumulated matrix (i.e. parent matrix * parent translation ) */
+ if (curBone->parent){
+ Mat4One (T_parlen);
+ T_parlen[3][1] = parlen;
+ Mat4MulMat4 (M_accumulatedMatrix, T_parlen, curBone->parent->posemat);
+ }
+ else
+ Mat4One (M_accumulatedMatrix);
+
+ /* Compose the matrix for this bone */
+ Mat4MulSerie (curBone->posemat, M_accumulatedMatrix, T_root, R_bmat, M_obmat, NULL, NULL, NULL, NULL);
+
+ precalc_bonelist_posemats(&curBone->childbase, length);
+ }
+}
+
+void precalc_armature_posemats (bArmature *arm)
+{
+ precalc_bonelist_posemats(&arm->bonebase, 0.0);
+}
+
+void precalc_bone_defmat (Bone *bone)
+{
+ Bone *curBone;
+#if 0
+ float restmat[4][4];
+ float posemat[4][4];
+ float imat[4][4];
+
+ /* Store restmat and restmat inverse - Calculate once when leaving editmode */
+ /* Store all bones' posemats - Do when applied */
+
+ /* EXPENSIVE! Don't do this! */
+ get_objectspace_bone_matrix(bone, restmat, 1, 0);
+ get_objectspace_bone_matrix(bone, posemat, 1, 1);
+ Mat4Invert (imat, restmat);
+ Mat4MulMat4 (bone->defmat, imat, posemat);
+ /* /EXPENSIVE */
+#else
+ Mat4MulMat4 (bone->defmat, bone->irestmat, bone->posemat);
+#endif
+ for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
+ precalc_bone_defmat(curBone);
+ }
+}
+
+void calc_bone_deform (Bone *bone, float weight, float *vec, float *co, float *contrib)
+{
+ float cop[3];
+
+ if (!weight)
+ return;
+
+ VECCOPY (cop, co);
+
+ Mat4MulVecfl(bone->defmat, cop);
+
+ vec[0]+=(cop[0]-co[0])*weight;
+ vec[1]+=(cop[1]-co[1])*weight;
+ vec[2]+=(cop[2]-co[2])*weight;
+
+ (*contrib)+=weight;
+}
+
+void calc_armature_deform (Object *ob, float *co, int index)
+{
+ bArmature *arm;
+ Bone *bone;
+ Bone *curBone;
+ float vec[3];
+ float contrib=0;
+ int i;
+ MDeformVert *dvert = g_dverts+index;
+
+ arm=g_defarm;
+ vec[0]=vec[1]=vec[2]=0;
+
+ /* Apply the object's matrix */
+ Mat4MulVecfl(g_premat, co);
+
+ if (g_dverts){
+ for (i=0; i<dvert->totweight; i++){
+ bone = dvert->dw[i].data;
+ if (bone) calc_bone_deform (bone, dvert->dw[i].weight, vec, co, &contrib);
+ }
+
+ if (contrib){
+ vec[0]/=contrib;
+ vec[1]/=contrib;
+ vec[2]/=contrib;
+ }
+ VecAddf (co, vec, co);
+ Mat4MulVecfl(g_postmat, co);
+ return;
+ }
+
+
+ // Count the number of interested bones
+ for (curBone = arm->bonebase.first; curBone; curBone=curBone->next)
+ calc_armature_deform_bonechildren (curBone, NULL, co, &contrib, ob->obmat);
+
+ // Do the deformation
+ for (curBone = arm->bonebase.first; curBone; curBone=curBone->next)
+ calc_armature_deform_bonechildren (curBone, vec, co, &contrib, ob->obmat);
+
+ VecAddf (co, vec, co);
+ Mat4MulVecfl(g_postmat, co);
+}
+
+void apply_pose_armature (bArmature* arm, bPose* pose, int doit)
+{
+ Bone *curBone;
+ for (curBone = arm->bonebase.first; curBone; curBone=curBone->next){
+ apply_pose_bonechildren (curBone, pose, doit);
+ }
+}
+
+void where_is_armature (Object *ob)
+{
+ where_is_object (ob);
+ where_is_armature_time(ob, (float)G.scene->r.cfra);
+}
+
+void where_is_armature_time (Object *ob, float ctime)
+{
+ bArmature *arm;
+
+ arm = get_armature(ob);
+ if (!arm)
+ return;
+
+ where_is_bonelist_time (ob, &arm->bonebase, ctime);
+
+}
+
+static void where_is_bonelist_time (Object *ob, ListBase *base, float ctime)
+{
+ Bone *curBone;
+
+ for (curBone=base->first; curBone; curBone=curBone->next){
+ if (!curBone->childbase.first)
+ where_is_bone1_time (ob, curBone, ctime);
+
+ where_is_bonelist_time(ob, &curBone->childbase, ctime);
+ }
+}
+static void apply_pose_bonechildren (Bone* bone, bPose* pose, int doit)
+{
+ Bone *curBone;
+ bPoseChannel *chan;
+
+ if (!pose){
+
+ bone->dsize[0]=bone->dsize[1]=bone->dsize[2]=1.0F;
+ bone->size[0]=bone->size[1]=bone->size[2]=1.0F;
+
+ bone->dquat[0]=bone->dquat[1]=bone->dquat[2]=bone->dquat[3]=0;
+ bone->quat[0]=bone->quat[1]=bone->quat[2]=bone->quat[3]=0.0F;
+
+ bone->dloc[0]=bone->dloc[1]=bone->dloc[2]=0.0F;
+ bone->loc[0]=bone->loc[1]=bone->loc[2]=0.0F;
+ }
+
+ // Ensure there is achannel for this bone
+ verify_pose_channel (pose, bone->name);
+
+ // Search the pose for a channel with the same name
+ if (pose){
+ for (chan=pose->chanbase.first; chan; chan=chan->next){
+ if (!strcmp (chan->name, bone->name)){
+ if (chan->flag & POSE_LOC)
+ memcpy (bone->loc, chan->loc, sizeof (bone->loc));
+ if (chan->flag & POSE_SIZE)
+ memcpy (bone->size, chan->size, sizeof (bone->size));
+ if (chan->flag & POSE_ROT)
+ memcpy (bone->quat, chan->quat, sizeof (bone->quat));
+
+ if (doit){
+ bone_to_mat4(bone, bone->obmat);
+ }
+ else{
+ Mat4CpyMat4 (bone->obmat, chan->obmat);
+ }
+
+
+ break;
+ }
+ }
+ }
+
+ for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
+ apply_pose_bonechildren (curBone, pose, doit);
+ }
+}
+
+void make_boneMatrixvr (float outmatrix[][4],float delta[3], float roll)
+/* Calculates the rest matrix of a bone based
+ On its vector and a roll around that vector */
+{
+ float nor[3],axis[3],target[3]={0,1,0};
+ float theta;
+ float rMatrix[3][3], bMatrix[3][3], fMatrix[3][3];
+
+ VECCOPY (nor,delta);
+ Normalise (nor);
+
+ /* Find Axis & Amount for bone matrix*/
+ Crossf (axis,target,nor);
+ Normalise (axis);
+ theta=(float) acos (Inpf (target,nor));
+
+ /* Make Bone matrix*/
+ VecRotToMat3(axis, theta, bMatrix);
+
+ /* Make Roll matrix*/
+ VecRotToMat3(nor, roll, rMatrix);
+
+ /* Combine and output result*/
+ Mat3MulMat3 (fMatrix,rMatrix,bMatrix);
+ Mat4CpyMat3 (outmatrix,fMatrix);
+}
+
+void make_boneMatrix (float outmatrix[][4], Bone *bone)
+/* Calculates the rest matrix of a bone based
+ On its vector and a roll around that vector */
+{
+ float delta[3];
+ float parmat[4][4], imat[4][4], obmat[4][4];
+
+ if (bone->parent){
+ VecSubf (delta, bone->parent->tail, bone->parent->head);
+ make_boneMatrixvr(parmat, delta, bone->parent->roll);
+ }
+ else{
+ Mat4One (parmat);
+ }
+
+ Mat4Invert (imat, parmat);
+
+ VecSubf (delta, bone->tail, bone->head);
+ make_boneMatrixvr(obmat, delta, bone->roll);
+
+ Mat4MulMat4(outmatrix, obmat, imat);
+
+}
+
+
+bArmature *add_armature()
+{
+ bArmature *arm;
+
+ arm= alloc_libblock (&G.main->armature, ID_AR, "Armature");
+
+ if(arm) {
+
+
+ }
+ return arm;
+}
+
+
+void free_boneChildren(Bone *bone)
+{
+ Bone *child;
+
+ if (bone) {
+
+ child=bone->childbase.first;
+ if (child){
+ while (child){
+ free_boneChildren (child);
+ child=child->next;
+ }
+ BLI_freelistN (&bone->childbase);
+ }
+ }
+}
+
+void free_bones (bArmature *arm)
+{
+ Bone *bone;
+ /* Free children (if any) */
+ bone= arm->bonebase.first;
+ if (bone) {
+ while (bone){
+ free_boneChildren (bone);
+ bone=bone->next;
+ }
+ }
+
+
+ BLI_freelistN(&arm->bonebase);
+}
+
+void free_armature(bArmature *arm)
+{
+ if (arm) {
+/* unlink_armature(arm);*/
+ free_bones(arm);
+ }
+}
+
+void make_local_armature(bArmature *arm)
+{
+ int local=0, lib=0;
+ Object *ob;
+ bArmature *newArm;
+
+ if (arm->id.lib==0)
+ return;
+ if (arm->id.us==1) {
+ arm->id.lib= 0;
+ arm->id.flag= LIB_LOCAL;
+ new_id(0, (ID*)arm, 0);
+ return;
+ }
+
+ if(local && lib==0) {
+ arm->id.lib= 0;
+ arm->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)arm, 0);
+ }
+ else if(local && lib) {
+ newArm= copy_armature(arm);
+ newArm->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==arm) {
+
+ if(ob->id.lib==0) {
+ ob->data= newArm;
+ newArm->id.us++;
+ arm->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+static void copy_bonechildren (Bone* newBone, Bone* oldBone)
+{
+ Bone *curBone, *newChildBone;
+
+ /* Copy this bone's list*/
+ duplicatelist (&newBone->childbase, &oldBone->childbase);
+
+ /* For each child in the list, update it's children*/
+ newChildBone=newBone->childbase.first;
+ for (curBone=oldBone->childbase.first;curBone;curBone=curBone->next){
+ newChildBone->parent=newBone;
+ copy_bonechildren(newChildBone,curBone);
+ newChildBone=newChildBone->next;
+ }
+}
+
+bArmature *copy_armature(bArmature *arm)
+{
+ bArmature *newArm;
+ Bone *oldBone, *newBone;
+
+ newArm= copy_libblock (arm);
+ duplicatelist(&newArm->bonebase, &arm->bonebase);
+
+ /* Duplicate the childrens' lists*/
+ newBone=newArm->bonebase.first;
+ for (oldBone=arm->bonebase.first;oldBone;oldBone=oldBone->next){
+ newBone->parent=NULL;
+ copy_bonechildren (newBone, oldBone);
+ newBone=newBone->next;
+ };
+
+ return newArm;
+}
+
+
+void bone_to_mat3(Bone *bone, float mat[][3]) /* no parent */
+{
+ float smat[3][3];
+ float rmat[3][3];
+/* float q1[4], vec[3];*/
+
+ /* size */
+/* if(bone->ipo) {
+ vec[0]= bone->size[0]+bone->dsize[0];
+ vec[1]= bone->size[1]+bone->dsize[1];
+ vec[2]= bone->size[2]+bone->dsize[2];
+ SizeToMat3(vec, smat);
+ }
+ else
+*/ {
+ SizeToMat3(bone->size, smat);
+ }
+
+ /* rot */
+ /*if(bone->flag & BONE_QUATROT) {
+ if(bone->ipo) {
+ QuatMul(q1, bone->quat, bone->dquat);
+ QuatToMat3(q1, rmat);
+ }
+ else
+ */ {
+ NormalQuat(bone->quat);
+ QuatToMat3(bone->quat, rmat);
+ }
+/* }
+*/
+ Mat3MulMat3(mat, rmat, smat);
+}
+
+void bone_to_mat4(Bone *bone, float mat[][4])
+{
+ float tmat[3][3];
+
+ bone_to_mat3(bone, tmat);
+
+ Mat4CpyMat3(mat, tmat);
+
+ VECCOPY(mat[3], bone->loc);
+// VecAddf(mat[3], mat[3], bone->loc);
+/* if(bone->ipo) {
+ mat[3][0]+= bone->dloc[0];
+ mat[3][1]+= bone->dloc[1];
+ mat[3][2]+= bone->dloc[2];
+ }
+*/
+}
+
+Bone *get_indexed_bone (bArmature *arm, int index)
+/*
+ Walk the list until the index is reached
+*/
+{
+ Bone *bone=NULL, *curBone;
+ int ref=index;
+
+ if (!arm)
+ return NULL;
+
+ for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
+ bone = get_indexed_bone_bonechildren (curBone, &ref);
+ if (bone)
+ return bone;
+ }
+
+ return bone;
+}
+
+Bone *get_named_bone (bArmature *arm, const char *name)
+/*
+ Walk the list until the bone is found
+*/
+{
+ Bone *bone=NULL, *curBone;
+
+ if (!arm) return NULL;
+
+ for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
+ bone = get_named_bone_bonechildren (curBone, name);
+ if (bone)
+ return bone;
+ }
+
+ return bone;
+}
+
+static Bone *get_indexed_bone_bonechildren (Bone *bone, int *index)
+{
+ Bone *curBone, *rbone;
+
+ if (!*index)
+ return bone;
+
+ (*index)--;
+
+ for (curBone=bone->childbase.first; curBone; curBone=curBone->next){
+ rbone=get_indexed_bone_bonechildren (curBone, index);
+ if (rbone)
+ return rbone;
+ }
+
+ return NULL;
+}
+
+static Bone *get_named_bone_bonechildren (Bone *bone, const char *name)
+{
+ Bone *curBone, *rbone;
+
+ if (!strcmp (bone->name, name))
+ return bone;
+
+ for (curBone=bone->childbase.first; curBone; curBone=curBone->next){
+ rbone=get_named_bone_bonechildren (curBone, name);
+ if (rbone)
+ return rbone;
+ }
+
+ return NULL;
+}
+
+void make_displists_by_armature (Object *ob)
+{
+ Base *base;
+
+ if (ob){
+ for (base= G.scene->base.first; base; base= base->next){
+ if ((ob==base->object->parent) && (base->lay & G.scene->lay))
+ if (base->object->partype==PARSKEL )
+ makeDispList(base->object);
+ }
+ }
+}
+
+void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed)
+/* Gets matrix that transforms the bone to object space */
+/* This function is also used to compute the orientation of the bone for display */
+{
+ Bone *curBone;
+
+ Bone *bonelist[256];
+ int bonecount=0, i;
+
+ Mat4One (M_accumulatedMatrix);
+
+ /* Build a list of bones from tip to root */
+ for (curBone=bone; curBone; curBone=curBone->parent){
+ bonelist[bonecount] = curBone;
+ bonecount++;
+ }
+
+ /* Count through the inverted list (i.e. iterate from root to tip)*/
+ for (i=0; i<bonecount; i++){
+ float T_root[4][4];
+ float T_len[4][4];
+ float R_bmat[4][4];
+ float M_obmat[4][4];
+ float M_boneMatrix[4][4];
+ float delta[3];
+
+ curBone = bonelist[bonecount-i-1];
+
+ /* Get the length translation (length along y axis) */
+ Mat4One (T_len);
+ T_len[3][1] = get_bone_length(curBone);
+
+ if ((curBone == bone) && (root))
+ Mat4One (T_len);
+
+ /* Get the bone's root offset (in the parent's coordinate system) */
+ Mat4One (T_root);
+ VECCOPY (T_root[3], curBone->head);
+
+ /* Compose the restmat */
+ VecSubf(delta, curBone->tail, curBone->head);
+ make_boneMatrixvr(R_bmat, delta, curBone->roll);
+
+
+ /* Retrieve the obmat (user transformation) */
+ if (posed)
+ Mat4CpyMat4 (M_obmat, curBone->obmat);
+ else
+ Mat4One (M_obmat);
+
+ /* Compose the matrix for this bone */
+#if 0
+ Mat4MulSerie (M_boneMatrix, M_accumulatedMatrix, T_root, M_obmat, R_bmat, T_len, NULL, NULL, NULL);
+#else
+ Mat4MulSerie (M_boneMatrix, M_accumulatedMatrix, T_root, R_bmat, M_obmat, T_len, NULL, NULL, NULL);
+#endif
+ Mat4CpyMat4 (M_accumulatedMatrix, M_boneMatrix);
+ }
+
+
+}
+
+void solve_posechain (PoseChain *chain)
+{
+ float goal[3];
+ int i;
+ Bone *curBone;
+ float M_obmat[4][4];
+ float M_basischange[4][4];
+ bPoseChannel *chan;
+
+ if (!chain->solver) return;
+
+ /**
+ * Transform the goal from worldspace
+ * to the coordinate system of the root
+ * of the chain. The matrix for this
+ * was computed when the chain was built
+ * in ik_chain_to_posechain
+ */
+
+ VECCOPY (goal, chain->goal);
+ Mat4MulVecfl (chain->goalinv, goal);
+
+ /* Solve the chain */
+
+ IK_SolveChain(chain->solver,
+ goal,
+ chain->tolerance,
+ chain->iterations,
+ 0.1f,
+ chain->solver->segments);
+
+ /* Copy the results back into the bones */
+ for (i = chain->solver->num_segments-1, curBone=chain->target->parent; i>=0; i--, curBone=curBone->parent){
+
+ /* Retrieve the delta rotation from the solver */
+ Mat4One(M_basischange);
+ Mat4CpyMat3(M_basischange, chain->solver->segments[i].basis_change);
+
+
+ /**
+ * Multiply the bone's usertransform by the
+ * basis change to get the new usertransform
+ */
+
+ Mat4CpyMat4 (M_obmat, curBone->obmat);
+ Mat4MulMat4 (curBone->obmat, M_basischange, M_obmat);
+
+ /* Store the solve results on the childrens' channels */
+ for (chan = chain->pose->chanbase.first; chan; chan=chan->next){
+ if (!strcmp (chan->name, curBone->name)){
+ Mat4CpyMat4 (chan->obmat, curBone->obmat);
+ break;
+ }
+ }
+
+ }
+}
+
+void free_posechain (PoseChain *chain)
+{
+ if (chain->solver) {
+ MEM_freeN (chain->solver->segments);
+ chain->solver->segments = NULL;
+ IK_FreeChain(chain->solver);
+ }
+ MEM_freeN (chain);
+}
+
+PoseChain *ik_chain_to_posechain (Object *ob, Bone *bone)
+{
+ IK_Segment_Extern *segs;
+ PoseChain *chain = NULL;
+ Bone *curBone, *rootBone;
+ int segcount, curseg, icurseg;
+ float imat[4][4];
+ Bone *bonelist[256];
+ float rootmat[4][4];
+ float bonespace[4][4];
+
+ /**
+ * Some interesting variables in this function:
+ *
+ * Bone->obmat Bone's user transformation;
+ * It is initialized in where_is_bone1_time
+ *
+ * rootmat Bone's coordinate system, computed by
+ * get_objectspace_bone_matrix. Takes all
+ * parents transformations into account.
+ */
+
+
+
+ /* Ensure that all of the bone parent matrices are correct */
+
+ /* Find the chain's root & count the segments needed */
+ segcount = 0;
+ for (curBone = bone; curBone; curBone=curBone->parent){
+ rootBone = curBone;
+ if (curBone!=bone){
+ bonelist[segcount]=curBone;
+ segcount++;
+ }
+ if (!curBone->parent)
+ break;
+ else if (!(curBone->flag & BONE_IK_TOPARENT))
+ break;
+ }
+
+ if (!segcount)
+ return NULL;
+
+
+ /**
+ * Initialize a record to store information about the original bones
+ * This will be the return value for this function.
+ */
+
+ chain = MEM_callocN(sizeof(PoseChain), "posechain");
+ chain->solver = IK_CreateChain();
+ chain->target = bone;
+ chain->root = rootBone;
+ chain->pose = ob->pose;
+
+ /* Allocate some IK segments */
+ segs = MEM_callocN (sizeof(IK_Segment_Extern)*segcount, "iksegments");
+
+
+ /**
+ * Remove the offset from the first bone in the chain and take the target to chainspace
+ */
+
+
+ get_objectspace_bone_matrix(rootBone, bonespace, 1, 1);
+ Mat4One (rootmat);
+ VECCOPY (rootmat[3], bonespace[3]);
+
+ /* Take the target to bonespace */
+ Mat4MulMat4 (imat, rootmat, ob->obmat);
+ Mat4Invert (chain->goalinv, imat);
+
+
+ /**
+ * Build matrices from the root to the tip
+ * We count backwards through the bone list (which is sorted tip to root)
+ * and forwards through the ik_segment list
+ */
+
+ for (curseg = segcount-1; curseg>=0; curseg--){
+ float M_basismat[4][4];
+ float R_parmat[4][4];
+ float iR_parmat[4][4];
+ float R_bonemat[4][4];
+
+ /* Retrieve the corresponding bone for this segment */
+ icurseg=segcount-curseg-1;
+ curBone = bonelist[curseg];
+
+ /* Get the basis matrix */
+ Mat4One (R_parmat);
+ get_objectspace_bone_matrix(curBone, R_bonemat, 1, 1);
+ R_bonemat[3][0]=R_bonemat[3][1]=R_bonemat[3][2]=0.0F;
+
+ if (curBone->parent && (curBone->flag & BONE_IK_TOPARENT)){
+ get_objectspace_bone_matrix(curBone->parent, R_parmat, 1, 1);
+ R_parmat[3][0]=R_parmat[3][1]=R_parmat[3][2]=0.0F;
+ }
+
+ Mat4Invert(iR_parmat, R_parmat);
+ Mat4MulMat4(M_basismat, R_bonemat, iR_parmat);
+
+ /* Copy the matrix into the basis and transpose */
+ Mat3CpyMat4(segs[icurseg].basis, M_basismat);
+ Mat3Transp(segs[icurseg].basis);
+
+ /* Fill out the IK segment */
+ segs[icurseg].length = get_bone_length(curBone);
+
+ };
+
+ IK_LoadChain(chain->solver, segs, segcount);
+ return chain;
+}
+
+
+
+void precalc_bonelist_irestmats (ListBase* bonelist)
+{
+ Bone *curbone;
+
+ if (!bonelist)
+ return;
+
+ for (curbone = bonelist->first; curbone; curbone=curbone->next){
+ precalc_bone_irestmat(curbone);
+ precalc_bonelist_irestmats(&curbone->childbase);
+ }
+}
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
new file mode 100644
index 00000000000..23927fd793c
--- /dev/null
+++ b/source/blender/blenkernel/intern/blender.c
@@ -0,0 +1,343 @@
+
+/* blender.c jan 94 MIXED MODEL
+ *
+ * algemene hulp funkties en data
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef WIN32
+ #include <unistd.h> // for read close
+ #include <sys/param.h> // for MAXPATHLEN
+#else
+ #include <io.h> // for open close read
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h> // for open
+
+#include "MEM_guardedalloc.h"
+#include "DNA_listBase.h"
+#include "DNA_sdna_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_object_types.h"
+#include "DNA_curve_types.h"
+
+#include "BLI_blenlib.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "DNA_screen_types.h"
+
+#include "BKE_library.h"
+#include "BKE_blender.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_scene.h"
+#include "BKE_effect.h"
+#include "BKE_curve.h"
+#include "BKE_font.h"
+
+#include "BKE_bad_level_calls.h" /* for BPY_do_pyscript */
+
+#include "BLO_readfile.h" /* for BLO_read_file */
+
+#include "BKE_bad_level_calls.h" // for freeAllRad editNurb free_editMesh free_editText free_editArmature
+#include "BKE_utildefines.h" // O_BINARY FALSE
+
+#include "nla.h"
+
+Global G;
+UserDef U;
+
+char versionstr[48]= "";
+
+/* ************************************************ */
+/* pushpop faciliteit: om tijdelijk data te bewaren */
+
+ListBase ppmain={0, 0};
+
+typedef struct PushPop {
+ struct PushPop *next, *prev;
+ void *data;
+ int len;
+} PushPop;
+
+void pushdata(void *data, int len)
+{
+ PushPop *pp;
+
+ pp= MEM_mallocN(sizeof(PushPop), "pushpop");
+ BLI_addtail(&ppmain, pp);
+ pp->data= MEM_mallocN(len, "pushpop");
+ pp->len= len;
+ memcpy(pp->data, data, len);
+}
+
+void popfirst(void *data)
+{
+ PushPop *pp;
+
+ pp= ppmain.first;
+ if(pp) {
+ memcpy(data, pp->data, pp->len);
+ BLI_remlink(&ppmain, pp);
+ MEM_freeN(pp->data);
+ MEM_freeN(pp);
+ }
+ else printf("error in popfirst\n");
+}
+
+void poplast(void *data)
+{
+ PushPop *pp;
+
+ pp= ppmain.last;
+ if(pp) {
+ memcpy(data, pp->data, pp->len);
+ BLI_remlink(&ppmain, pp);
+ MEM_freeN(pp->data);
+ MEM_freeN(pp);
+ }
+ else printf("error in poplast\n");
+}
+
+void free_pushpop()
+{
+ PushPop *pp;
+
+ pp= ppmain.first;
+ while(pp) {
+ BLI_remlink(&ppmain, pp);
+ MEM_freeN(pp->data);
+ MEM_freeN(pp);
+ }
+}
+
+void pushpop_test()
+{
+ if(ppmain.first) printf("pushpop not empty\n");
+ free_pushpop();
+}
+
+
+
+/* ********** vrijgeven ********** */
+
+void free_blender(void)
+{
+ free_main(G.main);
+ G.main= NULL;
+
+ IMB_freeImBufdata(); /* imbuf lib */
+}
+
+void duplicatelist(ListBase *list1, ListBase *list2) /* kopie van 2 naar 1 */
+{
+ struct Link *link1, *link2;
+
+ list1->first= list1->last= 0;
+
+ link2= list2->first;
+ while(link2) {
+
+ link1= MEM_dupallocN(link2);
+ BLI_addtail(list1, link1);
+
+ link2= link2->next;
+ }
+}
+
+void initglobals(void)
+{
+ memset(&G, 0, sizeof(Global));
+
+ U.savetime= 1;
+
+ G.animspeed= 4;
+
+ G.main= MEM_callocN(sizeof(Main), "initglobals");
+
+ strcpy(G.ima, "//");
+
+ G.version= BLENDER_VERSION;
+
+ G.order= 1;
+ G.order= (((char*)&G.order)[0])?L_ENDIAN:B_ENDIAN;
+
+ sprintf(versionstr, "www.blender.nl %d", G.version);
+
+ clear_workob(); /* object.c */
+}
+
+/***/
+
+static void clear_global(void) {
+ extern short winqueue_break; /* screen.c */
+
+ freeAllRad();
+ free_main(G.main); /* free all lib data */
+ freefastshade(); /* anders oude lampgegevens */
+
+
+ /* hangende vars voorkomen */
+ R.backbuf= 0;
+
+ /* force all queues to be left */
+ winqueue_break= 1;
+
+ if (G.obedit) {
+ freeNurblist(&editNurb);
+ free_editMesh();
+ free_editText();
+ free_editArmature();
+ }
+
+ G.curscreen= NULL;
+ G.scene= NULL;
+ G.main= NULL;
+
+ G.obedit= NULL;
+ G.obpose= NULL;
+ G.saction= NULL;
+ G.buts= NULL;
+ G.v2d= NULL;
+ G.vd= NULL;
+ G.soops= NULL;
+ G.sima= NULL;
+ G.sipo= NULL;
+
+ G.f &= ~(G_WEIGHTPAINT + G_VERTEXPAINT + G_FACESELECT);
+}
+
+static void setup_app_data(BlendFileData *bfd, char *filename) {
+ Object *ob;
+
+ clear_global();
+
+ G.save_over = 1;
+
+ G.main= bfd->main;
+ if (bfd->user) {
+ U= *bfd->user;
+ MEM_freeN(bfd->user);
+ }
+
+ R.winpos= bfd->winpos;
+ R.displaymode= bfd->displaymode;
+ G.curscreen= bfd->curscreen;
+ G.fileflags= bfd->fileflags;
+
+ G.scene= G.curscreen->scene;
+
+ /* weinig DispListen, wel text_to_curve */
+ // this should be removed!!! But first a better displist system (ton)
+ for (ob= G.main->object.first; ob; ob= ob->id.next) {
+ if(ob->type==OB_FONT) {
+ Curve *cu= ob->data;
+ if(cu->nurb.first==0) text_to_curve(ob, 0);
+ }
+ else if(ob->type==OB_MESH) {
+ makeDispList(ob);
+ if(ob->effect.first) object_wave(ob);
+ }
+ }
+
+ if (!G.background) {
+ setscreen(G.curscreen);
+ }
+ /* baseflags */
+ set_scene_bg(G.scene);
+
+ if (G.f & G_SCENESCRIPT) {
+ BPY_do_pyscript(&G.scene->id, SCRIPT_ONLOAD);
+ }
+
+ strcpy(G.sce, filename);
+ strcpy(G.main->name, filename); /* is gegarandeerd current file */
+
+ MEM_freeN(bfd);
+}
+
+int BKE_read_file(char *dir, void *type_r) {
+ BlendReadError bre;
+ BlendFileData *bfd;
+
+ if (!G.background)
+ waitcursor(1);
+
+ bfd= BLO_read_from_file(dir, &bre);
+ if (bfd) {
+ if (type_r)
+ *((BlenFileType*)type_r)= bfd->type;
+
+ setup_app_data(bfd, dir);
+ } else {
+ error("Loading %s failed: %s", dir, BLO_bre_as_string(bre));
+ }
+
+ if (!G.background)
+ waitcursor(0);
+
+ return (bfd?1:0);
+}
+
+int BKE_read_file_from_memory(char* filebuf, int filelength, void *type_r)
+{
+ BlendReadError bre;
+ BlendFileData *bfd;
+
+ if (!G.background)
+ waitcursor(1);
+
+ bfd= BLO_read_from_memory(filebuf, filelength, &bre);
+ if (bfd) {
+ if (type_r)
+ *((BlenFileType*)type_r)= bfd->type;
+
+ setup_app_data(bfd, "<memory>");
+ } else {
+ error("Loading failed: %s", BLO_bre_as_string(bre));
+ }
+
+ if (!G.background)
+ waitcursor(0);
+
+ return (bfd?1:0);
+}
diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c
new file mode 100644
index 00000000000..c5c4221a076
--- /dev/null
+++ b/source/blender/blenkernel/intern/bmfont.c
@@ -0,0 +1,293 @@
+/**
+ * bmfont.c
+ *
+ * 04-10-2000 frank
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ */
+
+/**
+ * Two external functions:
+ *
+ * void detectBitmapFont(ImBuf *ibuf)
+ * detects if an image buffer contains a bitmap font. It makes the
+ * specific bitmap data which is stored in the bitmap invisible to blender.
+ *
+ * void matrixGlyph(ImBuf * ibuf, unsigned short unicode, *float x 7)
+ * returns all the information about the character (unicode) in the floats
+ *
+ * Room for improvement:
+ * add kerning data in the bitmap
+ * all calculations in matrixGlyph() are static and could be done during
+ * initialization
+ */
+
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BKE_global.h"
+#include "IMB_imbuf_types.h"
+
+#include "BKE_bmfont.h"
+#include "BKE_bmfont_types.h"
+
+void printfGlyph(bmGlyph * glyph)
+{
+ printf("unicode: %d '%c'\n", glyph->unicode, glyph->unicode);
+ printf(" locx: %4d locy: %4d\n", glyph->locx, glyph->locy);
+ printf(" sizex: %3d sizey: %3d\n", glyph->sizex, glyph->sizey);
+ printf(" ofsx: %3d ofsy: %3d\n", glyph->ofsx, glyph->ofsy);
+ printf(" advan: %3d reser: %3d\n", glyph->advance, glyph->reserved);
+}
+
+#define MAX2(x,y) ( (x)>(y) ? (x) : (y) )
+#define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) )
+
+void calcAlpha(ImBuf * ibuf)
+{
+ int i;
+ char * rect;
+
+ if (ibuf) {
+ rect = (char *) ibuf->rect;
+ for (i = ibuf->x * ibuf->y ; i > 0 ; i--) {
+ rect[3] = MAX3(rect[0], rect[1], rect[2]);
+ rect += 4;
+ }
+ }
+}
+
+void readBitmapFontVersion0(ImBuf * ibuf, unsigned char * rect, int step)
+{
+ int glyphcount, bytes, i, index, linelength, ysize;
+ unsigned char * buffer;
+ bmFont * bmfont;
+
+ linelength = ibuf->x * step;
+
+ glyphcount = (rect[6 * step] << 8) | rect[7 * step];
+ bytes = ((glyphcount - 1) * sizeof(bmGlyph)) + sizeof(bmFont);
+
+ ysize = (bytes + (ibuf->x - 1)) / ibuf->x;
+
+ if (ysize < ibuf->y) {
+ // we're first going to copy all data into a liniar buffer.
+ // step can be 4 or 1 bytes, and the data is not sequential because
+ // the bitmap was flipped vertically.
+
+ buffer = MEM_mallocN(bytes, "readBitmapFontVersion0:buffer");
+
+ index = 0;
+ for (i = 0; i < bytes; i++) {
+ buffer[i] = rect[index];
+ index += step;
+ if (index >= linelength) {
+ // we've read one line, no skip to the line *before* that
+ rect -= linelength;
+ index -= linelength;
+ }
+ }
+
+ // we're now going to endian convert the data
+
+ bmfont = MEM_mallocN(bytes, "readBitmapFontVersion0:bmfont");
+ index = 0;
+
+ // first read the header
+ bmfont->magic[0] = buffer[index++];
+ bmfont->magic[1] = buffer[index++];
+ bmfont->magic[2] = buffer[index++];
+ bmfont->magic[3] = buffer[index++];
+ bmfont->version = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->glyphcount = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->xsize = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->ysize = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+
+ for (i = 0; i < bmfont->glyphcount; i++) {
+ bmfont->glyphs[i].unicode = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->glyphs[i].locx = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->glyphs[i].locy = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->glyphs[i].ofsx = buffer[index++];
+ bmfont->glyphs[i].ofsy = buffer[index++];
+ bmfont->glyphs[i].sizex = buffer[index++];
+ bmfont->glyphs[i].sizey = buffer[index++];
+ bmfont->glyphs[i].advance = buffer[index++];
+ bmfont->glyphs[i].reserved = buffer[index++];
+ if (G.f & G_DEBUG) {
+ printfGlyph(&bmfont->glyphs[i]);
+ }
+ }
+
+ MEM_freeN(buffer);
+
+ if (G.f & G_DEBUG) {
+ printf("Oldy = %d Newy = %d\n", ibuf->y, ibuf->y - ysize);
+ printf("glyphcount = %d\n", glyphcount);
+ printf("bytes = %d\n", bytes);
+ }
+
+ // we've read the data from the image. Now we're going
+ // to crop the image vertically so only the bitmap data
+ // remains visible
+
+ ibuf->y -= ysize;
+ ibuf->userdata = bmfont;
+ ibuf->userflags |= IB_BITMAPFONT;
+
+ if (ibuf->depth < 32) {
+ // we're going to fake alpha here:
+ calcAlpha(ibuf);
+ }
+ } else {
+ printf("readBitmapFontVersion0: corrupted bitmapfont\n");
+ }
+}
+
+void detectBitmapFont(ImBuf *ibuf)
+{
+ unsigned char * rect;
+ unsigned short version;
+ long i;
+
+ if (ibuf != NULL) {
+ // bitmap must have an x size that is a power of two
+ if (is_power_of_two(ibuf->x)) {
+ rect = (unsigned char *) (ibuf->rect + (ibuf->x * (ibuf->y - 1)));
+ // printf ("starts with: %s %c %c %c %c\n", rect, rect[0], rect[1], rect[2], rect[3]);
+ if (rect[0] == 'B' && rect[1] == 'F' && rect[2] == 'N' && rect[3] == 'T') {
+ // printf("found 8bit font !\n");
+ // round y size down
+ // do the 8 bit font stuff. (not yet)
+ } else {
+ // we try all 4 possible combinations
+ for (i = 0; i < 4; i++) {
+ if (rect[0] == 'B' && rect[4] == 'F' && rect[8] == 'N' && rect[12] == 'T') {
+ // printf("found 24bit font !\n");
+ // We're going to parse the file:
+
+ version = (rect[16] << 8) | rect[20];
+
+ if (version == 0) {
+ readBitmapFontVersion0(ibuf, rect, 4);
+ } else {
+ printf("detectBitmapFont :Unsupported version %d\n", version);
+ }
+
+ // on succes ibuf->userdata points to the bitmapfont
+ if (ibuf->userdata) {
+ break;
+ }
+ }
+ rect++;
+ }
+ }
+ }
+ }
+}
+
+int locateGlyph(bmFont *bmfont, unsigned short unicode)
+{
+ int min, max, current = 0;
+
+ if (bmfont) {
+ min = 0;
+ max = bmfont->glyphcount;
+ while (1) {
+ // look halfway for glyph
+ current = (min + max) >> 1;
+
+ if (bmfont->glyphs[current].unicode == unicode) {
+ break;
+ } else if (bmfont->glyphs[current].unicode < unicode) {
+ // have to move up
+ min = current;
+ } else {
+ // have to move down
+ max = current;
+ }
+
+ if (max - min <= 1) {
+ // unable to locate glyph
+ current = 0;
+ break;
+ }
+ }
+ }
+
+ return(current);
+}
+
+void matrixGlyph(ImBuf * ibuf, unsigned short unicode,
+ float *centerx, float *centery,
+ float *sizex, float *sizey,
+ float *transx, float *transy,
+ float *movex, float *movey,
+ float *advance)
+{
+ int index;
+ bmFont *bmfont;
+
+ *centerx = *centery = 0.0;
+ *sizex = *sizey = 1.0;
+ *transx = *transy = 0.0;
+ *movex = *movey = 0.0;
+ *advance = 1.0;
+
+ if (ibuf) {
+ bmfont = ibuf->userdata;
+ if (bmfont && (ibuf->userflags & IB_BITMAPFONT)) {
+ index = locateGlyph(bmfont, unicode);
+ if (index) {
+
+ *sizex = (bmfont->glyphs[index].sizex) / (float) (bmfont->glyphs[0].sizex);
+ *sizey = (bmfont->glyphs[index].sizey) / (float) (bmfont->glyphs[0].sizey);
+
+ *transx = bmfont->glyphs[index].locx / (float) ibuf->x;
+ *transy = (ibuf->y - bmfont->glyphs[index].locy) / (float) ibuf->y;
+
+ *centerx = bmfont->glyphs[0].locx / (float) ibuf->x;
+ *centery = (ibuf->y - bmfont->glyphs[0].locy) / (float) ibuf->y;
+
+ // 2.0 units is the default size of an object
+
+ *movey = 1.0f - *sizey + 2.0f * (bmfont->glyphs[index].ofsy - bmfont->glyphs[0].ofsy) / (float) bmfont->glyphs[0].sizey;
+ *movex = *sizex - 1.0f + 2.0f * (bmfont->glyphs[index].ofsx - bmfont->glyphs[0].ofsx) / (float) bmfont->glyphs[0].sizex;
+
+ *advance = 2.0f * bmfont->glyphs[index].advance / (float) bmfont->glyphs[0].advance;
+
+ // printfGlyph(&bmfont->glyphs[index]);
+ // printf("%c %d %0.5f %0.5f %0.5f %0.5f %0.5f \n", unicode, index, *sizex, *sizey, *transx, *transy, *advance);
+ }
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
new file mode 100644
index 00000000000..9c1a4607dca
--- /dev/null
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -0,0 +1,732 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "nla.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_object_types.h"
+#include "DNA_action_types.h"
+#include "DNA_curve_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_blender.h"
+#include "BKE_constraint.h"
+#include "BKE_object.h"
+#include "BKE_ipo.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+
+#include "blendef.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+/* Local function prototypes */
+static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], float size[3], float ctime);
+
+/* Functions */
+
+bConstraintChannel *find_constraint_channel (ListBase *list, const char *name){
+ bConstraintChannel *chan;
+
+ for (chan = list->first; chan; chan=chan->next){
+ if (!strcmp(name, chan->name)){
+ return chan;
+ }
+ }
+ return NULL;
+}
+
+void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime)
+{
+ bConstraint *con;
+ bConstraintChannel *chan;
+ IpoCurve *icu;
+
+ for (con=conbase->first; con; con=con->next){
+ chan = find_constraint_channel(chanbase, con->name);
+ if (chan && chan->ipo){
+ calc_ipo(chan->ipo, ctime);
+ for (icu=chan->ipo->curve.first; icu; icu=icu->next){
+ switch (icu->adrcode){
+ case CO_ENFORCE:
+ con->enforce = icu->curval;
+ if (con->enforce<0) con->enforce=0;
+ else if (con->enforce>1) con->enforce=1;
+ break;
+ }
+ }
+ }
+ }
+}
+
+void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight)
+{
+ float squat[4], dquat[4], fquat[4];
+ float ssize[3], dsize[3], fsize[4];
+ float sloc[3], dloc[3], floc[3];
+ float mat3[3][3], dstweight;
+ float qmat[3][3], smat[3][3];
+ int i;
+
+
+ dstweight = 1.0F-srcweight;
+
+ Mat3CpyMat4(mat3, dst);
+ Mat3ToQuat(mat3, dquat);
+ Mat3ToSize(mat3, dsize);
+ VECCOPY (dloc, dst[3]);
+
+ Mat3CpyMat4(mat3, src);
+ Mat3ToQuat(mat3, squat);
+ Mat3ToSize(mat3, ssize);
+ VECCOPY (sloc, src[3]);
+
+ /* Do the actual blend */
+ for (i=0; i<3; i++){
+ floc[i] = (dloc[i]*dstweight) + (sloc[i]*srcweight);
+ fsize[i] = 1.0f + ((dsize[i]-1.0f)*dstweight) + ((ssize[i]-1.0f)*srcweight);
+ fquat[i+1] = (dquat[i+1]*dstweight) + (squat[i+1]*srcweight);
+ }
+
+ /* Do one more iteration for the quaternions only and normalize the quaternion if needed */
+ fquat[0] = 1.0f + ((dquat[0]-1.0f)*dstweight) + ((squat[0]-1.0f)*srcweight);
+ NormalQuat (fquat);
+
+ QuatToMat3(fquat, qmat);
+ SizeToMat3(fsize, smat);
+
+ Mat3MulMat3(mat3, qmat, smat);
+ Mat4CpyMat3(out, mat3);
+ VECCOPY (out[3], floc);
+}
+
+static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], float size[3], float ctime)
+{
+
+ /* Update the location of the target object */
+ where_is_object_time (ob, ctime);
+
+ /* Case OBJECT */
+ if (!strlen(substring)){
+ Mat4CpyMat4 (mat, ob->obmat);
+ VECCOPY (size, ob->size);
+ return;
+ }
+
+ /* Case BONE */
+ else {
+ bArmature *arm;
+ Bone *bone;
+ float bmat[4][4];
+ float bsize[3]={1, 1, 1};
+
+ arm = get_armature(ob);
+
+ /**
+ * Locate the bone (if there is one)
+ * Ensures that the bone's transformation is fully constrained
+ * (Cyclical relationships are disallowed elsewhere)
+ */
+ bone = get_named_bone(arm, substring);
+ if (bone){
+ where_is_bone_time(ob, bone, ctime);
+ get_objectspace_bone_matrix(bone, bmat, 1, 1);
+ VECCOPY(bsize, bone->size);
+ }
+ else
+ Mat4One (bmat);
+
+ /**
+ * Multiply the objectspace bonematrix by the skeletons's global
+ * transform to obtain the worldspace transformation of the target
+ */
+ VECCOPY(size, bsize);
+ Mat4MulMat4 (mat, bmat, ob->obmat);
+
+ return;
+ }
+}
+
+void clear_object_constraint_status (Object *ob)
+{
+ bConstraint *con;
+
+ if (!ob) return;
+
+ /* Clear the object's constraints */
+ for (con = ob->constraints.first; con; con=con->next){
+ con->flag &= ~CONSTRAINT_DONE;
+ }
+
+ /* Clear the object's subdata constraints */
+ switch (ob->type){
+ case OB_ARMATURE:
+ {
+ clear_pose_constraint_status (ob);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+short get_constraint_target (bConstraint *con, short ownertype, void* ownerdata, float mat[][4], float size[3], float ctime)
+{
+ short valid=0;
+
+ switch (con->type){
+ case CONSTRAINT_TYPE_NULL:
+ {
+ Mat4One(mat);
+ }
+ break;
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ if (ownertype == TARGET_BONE){
+ bActionConstraint *data = (bActionConstraint*)con->data;
+ bPose *pose=NULL;
+ bPoseChannel *pchan=NULL;
+ float tempmat[4][4], imat[4][4], ans[4][4], restmat[4][4], irestmat[4][4];
+ float tempmat3[3][3];
+ float eul[3], size[3];
+ float s,t;
+ Bone *curBone;
+ Bone tbone;
+ int i;
+
+ curBone = (Bone*)ownerdata;
+
+ if (data->tar){
+ constraint_target_to_mat4(data->tar, data->subtarget, tempmat, size, ctime);
+ valid=1;
+ }
+ else
+ Mat4One (tempmat);
+
+ /* If this is a bone, undo parent transforms */
+ if (strlen(data->subtarget)){
+ Bone* bone;
+
+ Mat4Invert(imat, data->tar->obmat);
+ bone = get_named_bone(get_armature(data->tar), data->subtarget);
+ if (bone){
+ get_objectspace_bone_matrix(bone, restmat, 1, 0);
+ Mat4Invert(irestmat, restmat);
+ }
+ }
+ else{
+ Mat4One(imat);
+ Mat4One(irestmat);
+ }
+
+ Mat4MulSerie(ans, imat, tempmat, irestmat, NULL, NULL, NULL, NULL, NULL);
+
+ Mat3CpyMat4(tempmat3, ans);
+ Mat3ToEul(tempmat3, eul);
+
+ eul[0]*=(float)(180.0/M_PI);
+ eul[1]*=(float)(180.0/M_PI);
+ eul[2]*=(float)(180.0/M_PI);
+
+ /* Target is the animation */
+ s = (eul[data->type]-data->min)/(data->max-data->min);
+ if (s<0)
+ s=0;
+ if (s>1)
+ s=1;
+
+ t = ( s * (data->end-data->start)) + data->start;
+
+ /* Get the appropriate information from the action */
+ pose = MEM_callocN(sizeof(bPose), "pose");
+
+ verify_pose_channel(pose, curBone->name);
+ get_pose_from_action (&pose, data->act, t);
+
+ /* Find the appropriate channel */
+ pchan = get_pose_channel(pose, curBone->name);
+ if (pchan){
+ memset(&tbone, 0x00, sizeof(Bone));
+
+ VECCOPY (tbone.loc, pchan->loc);
+ VECCOPY (tbone.size, pchan->size);
+ for (i=0; i<4; i++)
+ tbone.quat[i]=pchan->quat[i];
+
+ bone_to_mat4(&tbone, mat);
+
+ }
+ else{
+ Mat4One(mat);
+ }
+ /* Clean up */
+ clear_pose(pose);
+ MEM_freeN(pose);
+ }
+
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data = (bLocateLikeConstraint*)con->data;
+
+ if (data->tar){
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
+ valid=1;
+ }
+ else
+ Mat4One (mat);
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data;
+ data = (bRotateLikeConstraint*)con->data;
+
+ if (data->tar){
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
+ valid=1;
+ }
+ else
+ Mat4One (mat);
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data;
+ data = (bTrackToConstraint*)con->data;
+
+ if (data->tar){
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
+ valid=1;
+ }
+ else
+ Mat4One (mat);
+ }
+ break;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bTrackToConstraint *data;
+ data = (bTrackToConstraint*)con->data;
+
+ if (data->tar){
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
+ valid=1;
+ }
+ else
+ Mat4One (mat);
+ }
+ break;
+ default:
+ Mat4One(mat);
+ break;
+ }
+
+ return valid;
+}
+
+void relink_constraints (struct ListBase *list)
+{
+ bConstraint *con;
+
+ for (con = list->first; con; con=con->next){
+ switch (con->type){
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data;
+ data = con->data;
+
+ ID_NEW(data->tar);
+ }
+ break;
+ case CONSTRAINT_TYPE_NULL:
+ {
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data;
+ data = con->data;
+
+ ID_NEW(data->tar);
+ }
+ break;
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data;
+ data = con->data;
+
+ ID_NEW(data->tar);
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data;
+ data = con->data;
+
+ ID_NEW(data->tar);
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data;
+ data = con->data;
+
+ ID_NEW(data->tar);
+ }
+ break;
+ }
+ }
+}
+
+void *copy_constraint_channels (ListBase *dst, ListBase *src)
+{
+ bConstraintChannel *dchan, *schan;
+ bConstraintChannel *newact=NULL;
+
+ dst->first=dst->last=NULL;
+ duplicatelist(dst, src);
+
+ for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next){
+ dchan->ipo = copy_ipo(schan->ipo);
+ }
+
+ return newact;
+}
+
+bConstraintChannel *clone_constraint_channels (ListBase *dst, ListBase *src, bConstraintChannel *oldact)
+{
+ bConstraintChannel *dchan, *schan;
+ bConstraintChannel *newact=NULL;
+
+ dst->first=dst->last=NULL;
+ duplicatelist(dst, src);
+
+ for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next){
+ id_us_plus((ID *)dchan->ipo);
+ if (schan==oldact)
+ newact=dchan;
+ }
+
+ return newact;
+}
+
+void copy_constraints (ListBase *dst, ListBase *src)
+{
+ bConstraint *con;
+
+ dst->first=dst->last=NULL;
+
+ duplicatelist (dst, src);
+
+ /* Update specific data */
+ if (!dst->first)
+ return;
+
+ for (con = dst->first; con; con=con->next){
+ switch (con->type){
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data;
+
+ con->data = MEM_dupallocN (con->data);
+ data = (bActionConstraint*) con->data;
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data;
+
+ con->data = MEM_dupallocN (con->data);
+ data = (bLocateLikeConstraint*) con->data;
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data;
+
+ con->data = MEM_dupallocN (con->data);
+ data = (bRotateLikeConstraint*) con->data;
+ }
+ break;
+ case CONSTRAINT_TYPE_NULL:
+ {
+ con->data = NULL;
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data;
+
+ con->data = MEM_dupallocN (con->data);
+ data = (bTrackToConstraint*) con->data;
+ }
+ break;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data;
+
+ con->data = MEM_dupallocN (con->data);
+ data = (bKinematicConstraint*) con->data;
+ }
+ break;
+ default:
+ con->data = MEM_dupallocN (con->data);
+ break;
+ }
+ }
+}
+
+void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, void *ownerdata, float targetmat[][4])
+/* ob is likely to be a workob */
+{
+ float M_oldmat[4][4];
+ float M_identity[4][4];
+ float enforce = 1.0;
+
+ if (!constraint || !ob)
+ return;
+
+ Mat4One (M_identity);
+
+ /* We've already been calculated */
+ if (constraint->flag & CONSTRAINT_DONE){
+ return;
+ }
+
+ switch (constraint->type){
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ float temp[4][4];
+ bActionConstraint *data;
+
+ data = constraint->data;
+ Mat4CpyMat4 (temp, ob->obmat);
+
+ Mat4MulMat4(ob->obmat, targetmat, temp);
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data;
+
+ data = constraint->data;
+
+ if (data->flag & LOCLIKE_X)
+ ob->obmat[3][0] = targetmat[3][0];
+ if (data->flag & LOCLIKE_Y)
+ ob->obmat[3][1] = targetmat[3][1];
+ if (data->flag & LOCLIKE_Z)
+ ob->obmat[3][2] = targetmat[3][2];
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ float tmat[4][4];
+ float size[3];
+
+ Mat4ToSize(ob->obmat, size);
+
+ Mat4CpyMat4 (tmat, targetmat);
+ Mat4Ortho(tmat);
+
+ ob->obmat[0][0] = tmat[0][0]*size[0];
+ ob->obmat[0][1] = tmat[0][1]*size[1];
+ ob->obmat[0][2] = tmat[0][2]*size[2];
+
+ ob->obmat[1][0] = tmat[1][0]*size[0];
+ ob->obmat[1][1] = tmat[1][1]*size[1];
+ ob->obmat[1][2] = tmat[1][2]*size[2];
+
+ ob->obmat[2][0] = tmat[2][0]*size[0];
+ ob->obmat[2][1] = tmat[2][1]*size[1];
+ ob->obmat[2][2] = tmat[2][2]*size[2];
+ }
+ break;
+ case CONSTRAINT_TYPE_NULL:
+ {
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data;
+ float size[3];
+
+ data=(bTrackToConstraint*)constraint->data;
+
+ if (data->tar){
+
+ Mat4ToSize (ob->obmat, size);
+
+ Mat4CpyMat4 (M_oldmat, ob->obmat);
+
+ // Clear the object's rotation
+ ob->obmat[0][0]=ob->size[0];
+ ob->obmat[0][1]=0;
+ ob->obmat[0][2]=0;
+ ob->obmat[1][0]=0;
+ ob->obmat[1][1]=ob->size[1];
+ ob->obmat[1][2]=0;
+ ob->obmat[2][0]=0;
+ ob->obmat[2][1]=0;
+ ob->obmat[2][2]=ob->size[2];
+
+ solve_tracking(ob, targetmat);
+ }
+ }
+ break;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data;
+ float imat[4][4];
+ float temp[4][4];
+ float totmat[4][4];
+
+ data=(bKinematicConstraint*)constraint->data;
+
+ if (data->tar && ownertype==TARGET_BONE && ownerdata){
+ Bone *curBone = (Bone*)ownerdata;
+ PoseChain *chain;
+ Object *armob;
+
+ /* Retrieve the owner armature object from the workob */
+ armob = ob->parent;
+
+ /* Make an IK chain */
+ chain = ik_chain_to_posechain(armob, curBone);
+ if (!chain)
+ return;
+ chain->iterations = data->iterations;
+ chain->tolerance = data->tolerance;
+
+
+ {
+ float parmat[4][4];
+
+ /* Take the obmat to objectspace */
+ Mat4CpyMat4 (temp, curBone->obmat);
+ Mat4One (curBone->obmat);
+ get_objectspace_bone_matrix(curBone, parmat, 1, 1);
+ Mat4CpyMat4 (curBone->obmat, temp);
+ Mat4MulMat4 (totmat, parmat, ob->parent->obmat);
+
+ Mat4Invert (imat, totmat);
+
+ Mat4CpyMat4 (temp, ob->obmat);
+ Mat4MulMat4 (ob->obmat, temp, imat);
+ }
+
+
+ /* Solve it */
+ if (chain->solver){
+ VECCOPY (chain->goal, targetmat[3]);
+ solve_posechain(chain);
+ }
+
+ free_posechain(chain);
+
+ {
+ float parmat[4][4];
+
+ /* Take the obmat to worldspace */
+ Mat4CpyMat4 (temp, curBone->obmat);
+ Mat4One (curBone->obmat);
+ get_objectspace_bone_matrix(curBone, parmat, 1, 1);
+ Mat4CpyMat4 (curBone->obmat, temp);
+ Mat4MulMat4 (totmat, parmat, ob->parent->obmat);
+
+ Mat4CpyMat4 (temp, ob->obmat);
+ Mat4MulMat4 (ob->obmat, temp, totmat);
+
+ }
+ }
+ }
+ break;
+ case CONSTRAINT_TYPE_FOLLOWPATH:
+ break;
+ default:
+ printf ("Error: Unknown constraint type\n");
+ break;
+ }
+
+}
+
+void free_constraint_data (bConstraint *con)
+{
+ if (con->data){
+ switch (con->type){
+ default:
+ break;
+ };
+
+ MEM_freeN (con->data);
+ }
+}
+
+void free_constraints (ListBase *conlist)
+{
+ bConstraint *con;
+
+ /* Do any specific freeing */
+ for (con=conlist->first; con; con=con->next)
+ {
+ free_constraint_data (con);
+ };
+
+ /* Free the whole list */
+ BLI_freelistN(conlist);
+}
+
+void free_constraint_channels (ListBase *chanbase)
+{
+ bConstraintChannel *chan;
+
+ for (chan=chanbase->first; chan; chan=chan->next)
+ {
+ if (chan->ipo){
+ chan->ipo->id.us--;
+ }
+ }
+
+ BLI_freelistN(chanbase);
+} \ No newline at end of file
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
new file mode 100644
index 00000000000..1f0c838e816
--- /dev/null
+++ b/source/blender/blenkernel/intern/curve.c
@@ -0,0 +1,2344 @@
+
+/* curve.c MIXED MODEL
+ *
+ * maart 95
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#define STRUBI hack
+
+#include <math.h> // floor
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_object_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+
+/* for dereferencing pointers */
+#include "DNA_ID.h"
+#include "DNA_vfont_types.h"
+#include "DNA_key_types.h"
+#include "DNA_ipo_types.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_utildefines.h" // VECCOPY
+#include "BKE_object.h"
+#include "BKE_mesh.h"
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+#include "BKE_ipo.h"
+#include "BKE_anim.h"
+#include "BKE_library.h"
+#include "BKE_key.h"
+
+
+/* globals */
+
+extern ListBase editNurb; /* editcurve.c */
+
+/* local */
+int cu_isectLL(float *v1, float *v2, float *v3, float *v4,
+ short cox, short coy,
+ float *labda, float *mu, float *vec);
+
+
+#ifdef STRUBI
+/* hotfix; copies x*y array into extended (x+dx)*(y+dy) array
+old[] and new[] can be the same ! */
+int copyintoExtendedArray(float *old, int oldx, int oldy, float *new, int newx, int newy)
+{
+ int x, y;
+ float *oldp, *newp;
+ if (newx < oldx || newy < oldy) return 0;
+
+
+ for (y = newy - 1; y >= oldy; y--) {
+ for (x = newx - 1; x >= 0; x--) {
+ newp = new + 3 * (y * newx + x);
+ newp[0] = 0.0; newp[1] = 0.0; newp[2] = 0.0;
+ }
+ }
+
+ for (; y >= 0; y--) {
+
+ for (x = newx - 1; x >= oldx; x--) {
+ newp = new + 3 * (y * newx + x);
+ newp[0] = 0.0; newp[1] = 0.0; newp[2] = 0.0;
+ }
+ for (; x >= 0; x--) {
+ oldp = old + 3 * (y * oldx + x);
+ newp = new + 3 * (y * newx + x);
+ VECCOPY(newp, oldp);
+ }
+ }
+ return 1;
+}
+#endif
+
+void unlink_curve(Curve *cu)
+{
+ int a;
+
+ for(a=0; a<cu->totcol; a++) {
+ if(cu->mat[a]) cu->mat[a]->id.us--;
+ cu->mat[a]= 0;
+ }
+ if(cu->vfont) cu->vfont->id.us--;
+ cu->vfont= 0;
+ if(cu->key) cu->key->id.us--;
+ cu->key= 0;
+ if(cu->ipo) cu->ipo->id.us--;
+ cu->ipo= 0;
+}
+
+
+/* niet curve zelf vrijgeven */
+void free_curve(Curve *cu)
+{
+
+ freeNurblist(&cu->nurb);
+ BLI_freelistN(&cu->bev);
+ freedisplist(&cu->disp);
+
+ unlink_curve(cu);
+
+ if(cu->mat) MEM_freeN(cu->mat);
+ if(cu->str) MEM_freeN(cu->str);
+ if(cu->bb) MEM_freeN(cu->bb);
+ if(cu->path) free_path(cu->path);
+}
+
+Curve *add_curve(int type)
+{
+ Curve *cu;
+ char *str;
+
+ if(type==OB_CURVE) str= "Curve";
+ else if(type==OB_SURF) str= "Surf";
+ else str= "Text";
+
+ cu= alloc_libblock(&G.main->curve, ID_CU, str);
+
+ cu->size[0]= cu->size[1]= cu->size[2]= 1.0;
+ cu->flag= CU_FRONT+CU_BACK;
+ cu->pathlen= 100;
+ cu->resolu= cu->resolv= 6;
+ cu->width= 1.0;
+ cu->spacing= cu->linedist= 1.0;
+ cu->fsize= 1.0;
+ cu->texflag= AUTOSPACE;
+
+ cu->bb= unit_boundbox();
+
+ return cu;
+}
+
+Curve *copy_curve(Curve *cu)
+{
+ Curve *cun;
+ int a;
+
+ cun= copy_libblock(cu);
+ cun->nurb.first= cun->nurb.last= 0;
+ duplicateNurblist( &(cun->nurb), &(cu->nurb));
+
+ cun->mat= MEM_dupallocN(cu->mat);
+ for(a=0; a<cun->totcol; a++) {
+ id_us_plus((ID *)cun->mat[a]);
+ }
+
+ cun->str= MEM_dupallocN(cu->str);
+ cun->bb= MEM_dupallocN(cu->bb);
+
+ cun->key= copy_key(cu->key);
+ if(cun->key) cun->key->from= (ID *)cun;
+
+ cun->disp.first= cun->disp.last= 0;
+ cun->bev.first= cun->bev.last= 0;
+ cun->path= 0;
+
+ /* ook single user ipo */
+ if(cun->ipo) cun->ipo= copy_ipo(cun->ipo);
+
+ id_us_plus((ID *)cun->vfont);
+
+ return cun;
+}
+
+void make_local_curve(Curve *cu)
+{
+ Object *ob = 0;
+ Curve *cun;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(cu->id.lib==0) return;
+
+ if(cu->vfont) cu->vfont->id.lib= 0;
+
+ if(cu->id.us==1) {
+ cu->id.lib= 0;
+ cu->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)cu, 0);
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==cu) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ cu->id.lib= 0;
+ cu->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)cu, 0);
+ }
+ else if(local && lib) {
+ cun= copy_curve(cu);
+ cun->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==cu) {
+
+ if(ob->id.lib==0) {
+ ob->data= cun;
+ cun->id.us++;
+ cu->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+
+void test_curve_type(Object *ob)
+{
+ Nurb *nu;
+ Curve *cu;
+
+ cu= ob->data;
+ if(cu->vfont) {
+ ob->type= OB_FONT;
+ return;
+ }
+ else {
+ nu= cu->nurb.first;
+ while(nu) {
+ if(nu->pntsv>1) {
+ ob->type= OB_SURF;
+ return;
+ }
+ nu= nu->next;
+ }
+ }
+ ob->type= OB_CURVE;
+}
+
+void tex_space_curve(Curve *cu)
+{
+ DispList *dl;
+ BoundBox *bb;
+ float *data, min[3], max[3], loc[3], size[3];
+ int tot, doit= 0;
+
+ if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
+ bb= cu->bb;
+
+ INIT_MINMAX(min, max);
+
+ dl= cu->disp.first;
+ while(dl) {
+
+ if(dl->type==DL_INDEX3 || dl->type==DL_INDEX3) tot= dl->nr;
+ else tot= dl->nr*dl->parts;
+
+ if(tot) doit= 1;
+ data= dl->verts;
+ while(tot--) {
+ DO_MINMAX(data, min, max);
+ data+= 3;
+ }
+ dl= dl->next;
+ }
+
+ if(doit) {
+ loc[0]= (min[0]+max[0])/2.0f;
+ loc[1]= (min[1]+max[1])/2.0f;
+ loc[2]= (min[2]+max[2])/2.0f;
+
+ size[0]= (max[0]-min[0])/2.0f;
+ size[1]= (max[1]-min[1])/2.0f;
+ size[2]= (max[2]-min[2])/2.0f;
+ }
+ else {
+ loc[0]= loc[1]= loc[2]= 0.0f;
+ size[0]= size[1]= size[2]= 1.0f;
+ }
+
+ bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= loc[0]-size[0];
+ bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= loc[0]+size[0];
+
+ bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= loc[1]-size[1];
+ bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= loc[1]+size[1];
+
+ bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= loc[2]-size[2];
+ bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= loc[2]+size[2];
+
+ if(cu->texflag & AUTOSPACE) {
+ VECCOPY(cu->loc, loc);
+ VECCOPY(cu->size, size);
+ cu->rot[0]= cu->rot[1]= cu->rot[2]= 0.0;
+
+ if(cu->size[0]==0.0) cu->size[0]= 1.0;
+ else if(cu->size[0]>0.0 && cu->size[0]<0.00001) cu->size[0]= 0.00001;
+ else if(cu->size[0]<0.0 && cu->size[0]> -0.00001) cu->size[0]= -0.00001;
+
+ if(cu->size[1]==0.0) cu->size[1]= 1.0;
+ else if(cu->size[1]>0.0 && cu->size[1]<0.00001) cu->size[1]= 0.00001;
+ else if(cu->size[1]<0.0 && cu->size[1]> -0.00001) cu->size[1]= -0.00001;
+
+ if(cu->size[2]==0.0) cu->size[2]= 1.0;
+ else if(cu->size[2]>0.0 && cu->size[2]<0.00001) cu->size[2]= 0.00001;
+ else if(cu->size[2]<0.0 && cu->size[2]> -0.00001) cu->size[2]= -0.00001;
+
+ }
+}
+
+
+int count_curveverts(ListBase *nurb)
+{
+ Nurb *nu;
+ int tot=0;
+
+ nu= nurb->first;
+ while(nu) {
+ if(nu->bezt) tot+= 3*nu->pntsu;
+ else if(nu->bp) tot+= nu->pntsu*nu->pntsv;
+
+ nu= nu->next;
+ }
+ return tot;
+}
+
+
+
+/* **************** NURBS ROUTINES ******************** */
+
+void freeNurb(Nurb *nu)
+{
+
+ if(nu==0) return;
+
+ if(nu->bezt) MEM_freeN(nu->bezt);
+ nu->bezt= 0;
+ if(nu->bp) MEM_freeN(nu->bp);
+ nu->bp= 0;
+ if(nu->knotsu) MEM_freeN(nu->knotsu);
+ nu->knotsu= 0;
+ if(nu->knotsv) MEM_freeN(nu->knotsv);
+ nu->knotsv= 0;
+ /* if(nu->trim.first) freeNurblist(&(nu->trim)); */
+
+ MEM_freeN(nu);
+
+}
+
+
+void freeNurblist(ListBase *lb)
+{
+ Nurb *nu, *next;
+
+ if(lb==0) return;
+
+ nu= lb->first;
+ while(nu) {
+ next= nu->next;
+ freeNurb(nu);
+ nu= next;
+ }
+ lb->first= lb->last= 0;
+}
+
+Nurb *duplicateNurb(Nurb *nu)
+{
+ Nurb *newnu;
+ int len;
+
+ newnu= (Nurb*)MEM_mallocN(sizeof(Nurb),"duplicateNurb");
+ if(newnu==0) return 0;
+ memcpy(newnu, nu, sizeof(Nurb));
+
+ if(nu->bezt) {
+ newnu->bezt=
+ (BezTriple*)MEM_mallocN((nu->pntsu)* sizeof(BezTriple),"duplicateNurb2");
+ memcpy(newnu->bezt, nu->bezt, nu->pntsu*sizeof(BezTriple));
+ }
+ else {
+ len= nu->pntsu*nu->pntsv;
+ newnu->bp=
+ (BPoint*)MEM_mallocN((len)* sizeof(BPoint),"duplicateNurb3");
+ memcpy(newnu->bp, nu->bp, len*sizeof(BPoint));
+
+ newnu->knotsu=newnu->knotsv= 0;
+
+ if(nu->knotsu) {
+ len= KNOTSU(nu);
+ if(len) {
+ newnu->knotsu= MEM_mallocN(len*sizeof(float), "duplicateNurb4");
+ memcpy(newnu->knotsu, nu->knotsu, sizeof(float)*len);
+ }
+ }
+ if(nu->pntsv>1 && nu->knotsv) {
+ len= KNOTSV(nu);
+ if(len) {
+ newnu->knotsv= MEM_mallocN(len*sizeof(float), "duplicateNurb5");
+ memcpy(newnu->knotsv, nu->knotsv, sizeof(float)*len);
+ }
+ }
+ }
+ return newnu;
+}
+
+void duplicateNurblist(ListBase *lb1, ListBase *lb2)
+{
+ Nurb *nu, *nun;
+
+ freeNurblist(lb1);
+
+ nu= lb2->first;
+ while(nu) {
+ nun= duplicateNurb(nu);
+ BLI_addtail(lb1, nun);
+
+ nu= nu->next;
+ }
+}
+
+void test2DNurb(Nurb *nu)
+{
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ if( nu->type== CU_BEZIER+CU_2D ) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ bezt->vec[0][2]= 0.0;
+ bezt->vec[1][2]= 0.0;
+ bezt->vec[2][2]= 0.0;
+ bezt++;
+ }
+ }
+ else if(nu->type & CU_2D) {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ bp->vec[2]= 0.0;
+ bp++;
+ }
+ }
+}
+
+void minmaxNurb(Nurb *nu, float *min, float *max)
+{
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ if( (nu->type & 7)==CU_BEZIER ) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ DO_MINMAX(bezt->vec[0], min, max);
+ DO_MINMAX(bezt->vec[1], min, max);
+ DO_MINMAX(bezt->vec[2], min, max);
+ bezt++;
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ DO_MINMAX(bp->vec, min, max);
+ bp++;
+ }
+ }
+
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline berekeningen ~~~~~~~~~~~ */
+
+
+/* voor de goede orde: eigenlijk horen hier doubles gebruikt te worden */
+
+void extend_spline(float * pnts, int in, int out)
+{
+ float *_pnts;
+ double * add;
+ int i, j, k;
+
+ _pnts = pnts;
+ add = (double*)MEM_mallocN((in)* sizeof(double), "extend_spline");
+
+ for (k = 3; k > 0; k--){
+ pnts = _pnts;
+
+ /* punten kopieren naar add */
+ for (i = 0; i < in; i++){
+ add[i] = *pnts;
+ pnts += 3;
+ }
+
+ /* inverse forward differencen */
+ for (i = 0; i < in - 1; i++){
+ for (j = in - 1; j > i; j--){
+ add[j] -= add[j - 1];
+ }
+ }
+
+ pnts = _pnts;
+ for (i = out; i > 0; i--){
+ *pnts = (float)(add[0]);
+ pnts += 3;
+ for (j = 0; j < in - 1; j++){
+ add[j] += add[j+1];
+ }
+ }
+
+ _pnts++;
+ }
+
+ MEM_freeN(add);
+}
+
+
+void calcknots(float *knots, short aantal, short order, short type)
+/* knots: aantal pnts NIET gecorrigeerd voor cyclic */
+/* aantal, order, type; 0: uniform, 1: endpoints, 2: bezier */
+{
+ float k;
+ int a;
+
+ if(type==0) {
+ for(a=0;a<aantal+order;a++) {
+ knots[a]= (float)a;
+ }
+ }
+ else if(type==1) {
+ k= 0.0;
+ for(a=1;a<=aantal+order;a++) {
+ knots[a-1]= k;
+ if(a>=order && a<=aantal) k+= 1.0;
+ }
+ }
+ else if(type==2) {
+ if(order==4) {
+ k= 0.34;
+ for(a=0;a<aantal+order;a++) {
+ knots[a]= (float)floor(k);
+ k+= (1.0/3.0);
+ }
+ }
+ else if(order==3) {
+ k= 0.6;
+ for(a=0;a<aantal+order;a++) {
+ if(a>=order && a<=aantal) k+= (0.5);
+ knots[a]= (float)floor(k);
+ }
+ }
+ }
+}
+
+void makecyclicknots(float *knots, short pnts, short order)
+/* pnts, order: aantal pnts NIET gecorrigeerd voor cyclic */
+{
+ int a, b;
+
+ if(knots==0) return;
+
+ /* eerst lange rijen (order -1) dezelfde knots aan uiteinde verwijderen */
+ if(order>2) {
+ b= pnts+order-1;
+ for(a=1; a<order-1; a++) {
+ if(knots[b]!= knots[b-a]) break;
+ }
+ if(a==order-1) knots[pnts+order-2]+= 1.0;
+ }
+
+ b= order;
+ for(a=pnts+order-1; a<pnts+order+order-1; a++) {
+ knots[a]= knots[a-1]+ (knots[b]-knots[b-1]);
+ b--;
+ }
+}
+
+
+void makeknots(Nurb *nu, short uv, short type) /* 0: uniform, 1: endpoints, 2: bezier */
+{
+ if( (nu->type & 7)==CU_NURBS ) {
+ if(uv & 1) {
+ if(nu->knotsu) MEM_freeN(nu->knotsu);
+ if(nu->pntsu>1) {
+ nu->knotsu= MEM_callocN(4+sizeof(float)*KNOTSU(nu), "makeknots");
+ calcknots(nu->knotsu, nu->pntsu, nu->orderu, type);
+ if(nu->flagu & 1) makecyclicknots(nu->knotsu, nu->pntsu, nu->orderu);
+ }
+ else nu->knotsu= 0;
+ }
+ if(uv & 2) {
+ if(nu->knotsv) MEM_freeN(nu->knotsv);
+ if(nu->pntsv>1) {
+ nu->knotsv= MEM_callocN(4+sizeof(float)*KNOTSV(nu), "makeknots");
+ calcknots(nu->knotsv, nu->pntsv, nu->orderv, type);
+ if(nu->flagv & 1) makecyclicknots(nu->knotsv, nu->pntsv, nu->orderv);
+ }
+ else nu->knotsv= 0;
+ }
+ }
+}
+
+void basisNurb(float t, short order, short pnts, float *knots, float *basis, int *start, int *end)
+{
+ float d, e;
+ int i, i1 = 0, i2 = 0 ,j, orderpluspnts;
+
+ orderpluspnts= order+pnts;
+
+ /* this is for float inaccuracy */
+ if(t < knots[0]) t= knots[0];
+ else if(t > knots[orderpluspnts-1]) t= knots[orderpluspnts-1];
+
+ /* dit stuk is order '1' */
+ for(i=0;i<orderpluspnts-1;i++) {
+ if(knots[i]!=knots[i+1] && t>= knots[i] && t<=knots[i+1]) {
+ basis[i]= 1.0;
+ i1= i-order+1;
+ if(i1<0) i1= 0;
+ i2= i;
+ i++;
+ while(i<orderpluspnts-1) {
+ basis[i]= 0.0;
+ i++;
+ }
+ break;
+ }
+ else basis[i]= 0.0;
+ }
+ basis[i]= 0.0;
+
+ /* printf("u %f\n", t); for(k=0;k<orderpluspnts;k++) printf(" %2.2f",basis[k]); printf("\n"); */
+
+ /* dit is order 2,3,... */
+ for(j=2; j<=order; j++) {
+
+ if(i2+j>= orderpluspnts) i2= orderpluspnts-j-1;
+
+ for(i= i1; i<=i2; i++) {
+ if(basis[i]!=0.0)
+ d= ((t-knots[i])*basis[i]) / (knots[i+j-1]-knots[i]);
+ else
+ d= 0.0;
+
+ if(basis[i+1]!=0.0)
+ e= ((knots[i+j]-t)*basis[i+1]) / (knots[i+j]-knots[i+1]);
+ else
+ e= 0.0;
+
+ basis[i]= d+e;
+ }
+ }
+
+ *start= 1000;
+ *end= 0;
+
+ for(i=i1; i<=i2; i++) {
+ if(basis[i]>0.0) {
+ *end= i;
+ if(*start==1000) *start= i;
+ }
+ }
+}
+
+
+void makeNurbfaces(Nurb *nu, float *data)
+/* data moet 3*4*resolu*resolv lang zijn en op nul staan */
+{
+ BPoint *bp;
+ float *basisu, *basis, *basisv, *sum, *fp, *in;
+ float u, v, ustart, uend, ustep, vstart, vend, vstep, sumdiv;
+ int i, j, iofs, jofs, cycl, len, resolu, resolv;
+ int istart, iend, jsta, jen, *jstart, *jend, ratcomp;
+
+ if(nu->knotsu==0 || nu->knotsv==0) return;
+ if(nu->orderu>nu->pntsu) return;
+ if(nu->orderv>nu->pntsv) return;
+ if(data==0) return;
+
+ /* alloceren en vars goedzetten */
+ len= nu->pntsu*nu->pntsv;
+ if(len==0) return;
+ sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbfaces1");
+
+ resolu= nu->resolu;
+ resolv= nu->resolv;
+ len= resolu*resolv;
+ if(len==0) {
+ MEM_freeN(sum);
+ return;
+ }
+
+ bp= nu->bp;
+ i= nu->pntsu*nu->pntsv;
+ ratcomp=0;
+ while(i--) {
+ if(bp->vec[3]!=1.0) {
+ ratcomp= 1;
+ break;
+ }
+ bp++;
+ }
+
+ fp= nu->knotsu;
+ ustart= fp[nu->orderu-1];
+ if(nu->flagu & 1) uend= fp[nu->pntsu+nu->orderu-1];
+ else uend= fp[nu->pntsu];
+ ustep= (uend-ustart)/(resolu-1+(nu->flagu & 1));
+ basisu= (float *)MEM_mallocN(sizeof(float)*KNOTSU(nu), "makeNurbfaces3");
+
+ fp= nu->knotsv;
+ vstart= fp[nu->orderv-1];
+
+ if(nu->flagv & 1) vend= fp[nu->pntsv+nu->orderv-1];
+ else vend= fp[nu->pntsv];
+ vstep= (vend-vstart)/(resolv-1+(nu->flagv & 1));
+ len= KNOTSV(nu);
+ basisv= (float *)MEM_mallocN(sizeof(float)*len*resolv, "makeNurbfaces3");
+ jstart= (int *)MEM_mallocN(sizeof(float)*resolv, "makeNurbfaces4");
+ jend= (int *)MEM_mallocN(sizeof(float)*resolv, "makeNurbfaces5");
+
+ /* voorberekenen basisv en jstart,jend */
+ if(nu->flagv & 1) cycl= nu->orderv-1;
+ else cycl= 0;
+ v= vstart;
+ basis= basisv;
+ while(resolv--) {
+ basisNurb(v, nu->orderv, (short)(nu->pntsv+cycl), nu->knotsv, basis, jstart+resolv, jend+resolv);
+ basis+= KNOTSV(nu);
+ v+= vstep;
+ }
+
+ if(nu->flagu & 1) cycl= nu->orderu-1;
+ else cycl= 0;
+ in= data;
+ u= ustart;
+ while(resolu--) {
+
+ basisNurb(u, nu->orderu, (short)(nu->pntsu+cycl), nu->knotsu, basisu, &istart, &iend);
+
+ basis= basisv;
+ resolv= nu->resolv;
+ while(resolv--) {
+
+ jsta= jstart[resolv];
+ jen= jend[resolv];
+
+ /* bereken sum */
+ sumdiv= 0.0;
+ fp= sum;
+
+ for(j= jsta; j<=jen; j++) {
+
+ if(j>=nu->pntsv) jofs= (j - nu->pntsv);
+ else jofs= j;
+ bp= nu->bp+ nu->pntsu*jofs+istart-1;
+
+ for(i= istart; i<=iend; i++, fp++) {
+
+ if(i>= nu->pntsu) {
+ iofs= i- nu->pntsu;
+ bp= nu->bp+ nu->pntsu*jofs+iofs;
+ }
+ else bp++;
+
+ if(ratcomp) {
+ *fp= basisu[i]*basis[j]*bp->vec[3];
+ sumdiv+= *fp;
+ }
+ else *fp= basisu[i]*basis[j];
+ }
+ }
+
+ if(ratcomp) {
+ fp= sum;
+ for(j= jsta; j<=jen; j++) {
+ for(i= istart; i<=iend; i++, fp++) {
+ *fp/= sumdiv;
+ }
+ }
+ }
+
+ /* een! (1.0) echt punt nu */
+ fp= sum;
+ for(j= jsta; j<=jen; j++) {
+
+ if(j>=nu->pntsv) jofs= (j - nu->pntsv);
+ else jofs= j;
+ bp= nu->bp+ nu->pntsu*jofs+istart-1;
+
+ for(i= istart; i<=iend; i++, fp++) {
+
+ if(i>= nu->pntsu) {
+ iofs= i- nu->pntsu;
+ bp= nu->bp+ nu->pntsu*jofs+iofs;
+ }
+ else bp++;
+
+ if(*fp!=0.0) {
+ in[0]+= (*fp) * bp->vec[0];
+ in[1]+= (*fp) * bp->vec[1];
+ in[2]+= (*fp) * bp->vec[2];
+ }
+ }
+ }
+
+ in+=3;
+ basis+= KNOTSV(nu);
+ }
+ u+= ustep;
+ }
+
+ /* vrijgeven */
+ MEM_freeN(sum);
+ MEM_freeN(basisu);
+ MEM_freeN(basisv);
+ MEM_freeN(jstart);
+ MEM_freeN(jend);
+}
+
+
+void makeNurbcurve_forw(Nurb *nu, float *data)
+/* *data: moet 3*4*pntsu*resolu lang zijn en op nul staan */
+{
+ BPoint *bp;
+ float *basisu, *sum, *fp, *in;
+ float u, ustart, uend, ustep, sumdiv;
+ int i, j, k, len, resolu, istart, iend;
+ int wanted, org;
+
+ if(nu->knotsu==0) return;
+ if(data==0) return;
+
+ /* alloceren en vars goedzetten */
+ len= nu->pntsu;
+ if(len==0) return;
+ sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbcurve1");
+
+ resolu= nu->resolu*nu->pntsu;
+ if(resolu==0) {
+ MEM_freeN(sum);
+ return;
+ }
+
+ fp= nu->knotsu;
+ ustart= fp[nu->orderu-1];
+ uend= fp[nu->pntsu];
+ ustep= (uend-ustart)/(resolu-1);
+ basisu= (float *)MEM_mallocN(sizeof(float)*(nu->orderu+nu->pntsu), "makeNurbcurve3");
+
+ in= data;
+ u= ustart;
+ for (k = nu->orderu - 1; k < nu->pntsu; k++){
+
+ wanted = (int)((nu->knotsu[k+1] - nu->knotsu[k]) / ustep);
+ org = 4; /* gelijk aan order */
+ if (org > wanted) org = wanted;
+
+ for (j = org; j > 0; j--){
+
+ basisNurb(u, nu->orderu, nu->pntsu, nu->knotsu, basisu, &istart, &iend);
+ /* bereken sum */
+ sumdiv= 0.0;
+ fp= sum;
+ for(i= istart; i<=iend; i++, fp++) {
+ /* hier nog rationele component doen */
+ *fp= basisu[i];
+ sumdiv+= *fp;
+ }
+ if(sumdiv!=0.0) if(sumdiv<0.999 || sumdiv>1.001) {
+ /* is dit normaliseren ook nodig? */
+ fp= sum;
+ for(i= istart; i<=iend; i++, fp++) {
+ *fp/= sumdiv;
+ }
+ }
+
+ /* een! (1.0) echt punt nu */
+ fp= sum;
+ bp= nu->bp+ istart;
+ for(i= istart; i<=iend; i++, bp++, fp++) {
+
+ if(*fp!=0.0) {
+ in[0]+= (*fp) * bp->vec[0];
+ in[1]+= (*fp) * bp->vec[1];
+ in[2]+= (*fp) * bp->vec[2];
+ }
+ }
+
+ in+=3;
+
+ u+= ustep;
+ }
+
+ if (wanted > org){
+ extend_spline(in - 3 * org, org, wanted);
+ in += 3 * (wanted - org);
+ u += ustep * (wanted - org);
+ }
+ }
+
+ /* vrijgeven */
+ MEM_freeN(sum);
+ MEM_freeN(basisu);
+}
+
+
+void makeNurbcurve(Nurb *nu, float *data, int dim)
+/* data moet dim*4*pntsu*resolu lang zijn en op nul staan */
+{
+ BPoint *bp;
+ float u, ustart, uend, ustep, sumdiv;
+ float *basisu, *sum, *fp, *in;
+ int i, len, resolu, istart, iend, cycl;
+
+ if(nu->knotsu==0) return;
+ if(nu->orderu>nu->pntsu) return;
+ if(data==0) return;
+
+ /* alloceren en vars goedzetten */
+ len= nu->pntsu;
+ if(len==0) return;
+ sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbcurve1");
+
+ resolu= nu->resolu*nu->pntsu;
+ if(resolu==0) {
+ MEM_freeN(sum);
+ return;
+ }
+
+ fp= nu->knotsu;
+ ustart= fp[nu->orderu-1];
+ if(nu->flagu & 1) uend= fp[nu->pntsu+nu->orderu-1];
+ else uend= fp[nu->pntsu];
+ ustep= (uend-ustart)/(resolu-1+(nu->flagu & 1));
+ basisu= (float *)MEM_mallocN(sizeof(float)*KNOTSU(nu), "makeNurbcurve3");
+
+ if(nu->flagu & 1) cycl= nu->orderu-1;
+ else cycl= 0;
+
+ in= data;
+ u= ustart;
+ while(resolu--) {
+
+ basisNurb(u, nu->orderu, (short)(nu->pntsu+cycl), nu->knotsu, basisu, &istart, &iend);
+ /* bereken sum */
+ sumdiv= 0.0;
+ fp= sum;
+ bp= nu->bp+ istart-1;
+ for(i= istart; i<=iend; i++, fp++) {
+
+ if(i>=nu->pntsu) bp= nu->bp+(i - nu->pntsu);
+ else bp++;
+
+ *fp= basisu[i]*bp->vec[3];
+ sumdiv+= *fp;
+ }
+ if(sumdiv!=0.0) if(sumdiv<0.999 || sumdiv>1.001) {
+ /* is dit normaliseren ook nodig? */
+ fp= sum;
+ for(i= istart; i<=iend; i++, fp++) {
+ *fp/= sumdiv;
+ }
+ }
+
+ /* een! (1.0) echt punt nu */
+ fp= sum;
+ bp= nu->bp+ istart-1;
+ for(i= istart; i<=iend; i++, fp++) {
+
+ if(i>=nu->pntsu) bp= nu->bp+(i - nu->pntsu);
+ else bp++;
+
+ if(*fp!=0.0) {
+
+ in[0]+= (*fp) * bp->vec[0];
+ in[1]+= (*fp) * bp->vec[1];
+ if(dim>=3) {
+ in[2]+= (*fp) * bp->vec[2];
+ if(dim==4) in[3]+= (*fp) * bp->alfa;
+ }
+ }
+ }
+
+ in+= dim;
+
+ u+= ustep;
+ }
+
+ /* vrijgeven */
+ MEM_freeN(sum);
+ MEM_freeN(basisu);
+}
+
+void maakbez(float q0, float q1, float q2, float q3, float *p, int it)
+{
+ float rt0,rt1,rt2,rt3,f;
+ int a;
+
+ f= (float)it;
+ rt0= q0;
+ rt1= 3.0f*(q1-q0)/f;
+ f*= f;
+ rt2= 3.0f*(q0-2.0f*q1+q2)/f;
+ f*= it;
+ rt3= (q3-q0+3.0f*(q1-q2))/f;
+
+ q0= rt0;
+ q1= rt1+rt2+rt3;
+ q2= 2*rt2+6*rt3;
+ q3= 6*rt3;
+
+ for(a=0; a<=it; a++) {
+ *p= q0;
+ p+= 3;
+ q0+= q1;
+ q1+= q2;
+ q2+= q3;
+ }
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+void make_orco_surf(Curve *cu)
+{
+ Nurb *nu;
+ int a, b, tot=0;
+ int sizeu, sizev;// ###
+ float *data;
+
+
+ /* eerst voorspellen hoelang datablok moet worden */
+ nu= cu->nurb.first;
+ while(nu) {
+#ifdef STRUBI
+/* this is a bad hack: as we want to avoid the seam in a cyclic nurbs
+texture wrapping, reserve extra orco data space to save these extra needed
+vertex based UV coordinates for the meridian vertices.
+Vertices on the 0/2pi boundary are not duplicated inside the displist but later in
+the renderface/vert construction.
+
+See also blenderWorldManipulation.c: init_render_surf()
+
+*/
+
+ sizeu = nu->resolu; sizev = nu->resolv;
+ if (nu->flagu & CU_CYCLIC) sizeu++;
+ if (nu->flagv & CU_CYCLIC) sizev++;
+ if(nu->pntsv>1) tot+= sizeu * sizev;
+#else
+ if(nu->pntsv>1) tot+= nu->resolu*nu->resolv;
+#endif
+ nu= nu->next;
+ }
+ /* makeNurbfaces wil nullen */
+ data= cu->orco= MEM_callocN(3*sizeof(float)*tot, "make_orco");
+
+ nu= cu->nurb.first;
+ while(nu) {
+ if(nu->pntsv>1) {
+ sizeu = nu->resolu;
+ sizev = nu->resolv;
+#ifdef STRUBI
+ if (nu->flagu & CU_CYCLIC) sizeu++;
+ if (nu->flagv & CU_CYCLIC) sizev++;
+#endif
+
+ if(cu->flag & CU_UV_ORCO) {
+ for(b=0; b< sizeu; b++) {
+ for(a=0; a< sizev; a++) {
+
+ if(sizev <2) data[0]= 0.0f;
+ else data[0]= -1.0f + 2.0f*((float)a)/(sizev - 1);
+
+ if(sizeu <2) data[1]= 0.0f;
+ else data[1]= -1.0f + 2.0f*((float)b)/(sizeu - 1);
+
+ data[2]= 0.0;
+
+ data+= 3;
+ }
+ }
+ }
+ else {
+ makeNurbfaces(nu, data);
+#ifdef STRUBI
+ for(b=0; b< nu->resolu; b++) {
+ for(a=0; a< nu->resolv; a++) {
+ data = cu->orco + 3 * (b * nu->resolv + a);
+ data[0]= (data[0]-cu->loc[0])/cu->size[0];
+ data[1]= (data[1]-cu->loc[1])/cu->size[1];
+ data[2]= (data[2]-cu->loc[2])/cu->size[2];
+ }
+ }
+ copyintoExtendedArray(cu->orco, nu->resolv, nu->resolu, cu->orco, sizev, sizeu);
+ /* copy U/V-cyclic orco's */
+ if (nu->flagv & CU_CYCLIC) {
+ b = sizeu - 1;
+ for(a=0; a< sizev; a++) {
+ data = cu->orco + 3 * (b * sizev + a);
+ VECCOPY(data, cu->orco + 3*a);
+ }
+ }
+ if (nu->flagu & CU_CYCLIC) {
+ a = sizev - 1;
+ for(b=0; b< sizeu; b++) {
+ data = cu->orco + 3 * (b * sizev + a);
+ VECCOPY(data, cu->orco + 3 * b*sizev);
+ }
+ }
+
+#else
+ tot= sizeu * sizev;
+ while(tot--) {
+ data[0]= (data[0]-cu->loc[0])/cu->size[0];
+ data[1]= (data[1]-cu->loc[1])/cu->size[1];
+ data[2]= (data[2]-cu->loc[2])/cu->size[2];
+
+ data+= 3;
+ }
+#endif
+ }
+ }
+ nu= nu->next;
+ }
+ /* loadkeypostype(22, base, base); */
+
+}
+
+
+
+/* ***************** BEVEL ****************** */
+
+void makebevelcurve(Object *ob, ListBase *disp)
+{
+ DispList *dl, *dlnew;
+ Curve *bevcu, *cu;
+ float *fp, facx, facy, hoek, dhoek;
+ int nr, a;
+
+ cu= ob->data;
+
+ if(cu->bevobj && cu->bevobj!=ob) {
+ if(cu->bevobj->type==OB_CURVE) {
+ bevcu= cu->bevobj->data;
+ if(bevcu->ext1==0.0 && bevcu->ext2==0.0) {
+ facx= cu->bevobj->size[0];
+ facy= cu->bevobj->size[1];
+
+ dl= bevcu->disp.first;
+ if(dl==0) {
+ makeDispList(cu->bevobj);
+ dl= bevcu->disp.first;
+ }
+ while(dl) {
+ if ELEM(dl->type, DL_POLY, DL_SEGM) {
+ dlnew= MEM_mallocN(sizeof(DispList), "makebevelcurve1");
+ *dlnew= *dl;
+ dlnew->verts= MEM_mallocN(3*sizeof(float)*dl->parts*dl->nr, "makebevelcurve1");
+ memcpy(dlnew->verts, dl->verts, 3*sizeof(float)*dl->parts*dl->nr);
+
+ BLI_addtail(disp, dlnew);
+ fp= dlnew->verts;
+ nr= dlnew->parts*dlnew->nr;
+ while(nr--) {
+ fp[2]= fp[1]*facy;
+ fp[1]= -fp[0]*facx;
+ fp[0]= 0.0;
+ fp+= 3;
+ }
+ }
+ dl= dl->next;
+ }
+ }
+ }
+ }
+ else if(cu->ext2==0.0) {
+ dl= MEM_callocN(sizeof(DispList), "makebevelcurve2");
+ dl->verts= MEM_mallocN(2*3*sizeof(float), "makebevelcurve2");
+ BLI_addtail(disp, dl);
+ dl->type= DL_SEGM;
+ dl->parts= 1;
+ dl->nr= 2;
+ fp= dl->verts;
+ fp[0]= fp[1]= 0.0;
+ fp[2]= -cu->ext1;
+ fp[3]= fp[4]= 0.0;
+ fp[5]= cu->ext1;
+ }
+ else {
+ nr= 4+2*cu->bevresol;
+
+ dl= MEM_callocN(sizeof(DispList), "makebevelcurve3");
+ dl->verts= MEM_mallocN(nr*3*sizeof(float), "makebevelcurve3");
+ BLI_addtail(disp, dl);
+ dl->type= DL_SEGM;
+ dl->parts= 1;
+ dl->nr= nr;
+
+ /* eerst cirkel maken */
+ fp= dl->verts;
+ hoek= -0.5*M_PI;
+ dhoek= (float)(M_PI/(nr-2));
+ for(a=0; a<nr; a++) {
+ fp[0]= 0.0;
+ fp[1]= (float)(cos(hoek)*(cu->ext2));
+ fp[2]= (float)(sin(hoek)*(cu->ext2));
+ hoek+= dhoek;
+ fp+= 3;
+ if(cu->ext1!=0.0 && a==((nr/2)-1) ) {
+ VECCOPY(fp, fp-3);
+ fp+=3;
+ a++;
+ }
+ }
+ if(cu->ext1==0.0) dl->nr--;
+ else {
+ fp= dl->verts;
+ for(a=0; a<nr; a++) {
+ if(a<=(nr/2-1)) fp[2]-= (cu->ext1);
+ else fp[2]+= (cu->ext1);
+ fp+= 3;
+ }
+ }
+ }
+
+}
+
+int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec)
+{
+ /* return:
+ -1: colliniar
+ 0: no intersection of segments
+ 1: exact intersection of segments
+ 2: cross-intersection of segments
+ */
+ float deler;
+
+ deler= (v1[cox]-v2[cox])*(v3[coy]-v4[coy])-(v3[cox]-v4[cox])*(v1[coy]-v2[coy]);
+ if(deler==0.0) return -1;
+
+ *labda= (v1[coy]-v3[coy])*(v3[cox]-v4[cox])-(v1[cox]-v3[cox])*(v3[coy]-v4[coy]);
+ *labda= -(*labda/deler);
+
+ deler= v3[coy]-v4[coy];
+ if(deler==0) {
+ deler=v3[cox]-v4[cox];
+ *mu= -(*labda*(v2[cox]-v1[cox])+v1[cox]-v3[cox])/deler;
+ } else {
+ *mu= -(*labda*(v2[coy]-v1[coy])+v1[coy]-v3[coy])/deler;
+ }
+ vec[cox]= *labda*(v2[cox]-v1[cox])+v1[cox];
+ vec[coy]= *labda*(v2[coy]-v1[coy])+v1[coy];
+
+ if(*labda>=0.0 && *labda<=1.0 && *mu>=0.0 && *mu<=1.0) {
+ if(*labda==0.0 || *labda==1.0 || *mu==0.0 || *mu==1.0) return 1;
+ return 2;
+ }
+ return 0;
+}
+
+
+short bevelinside(BevList *bl1,BevList *bl2)
+{
+ /* is bl2 INSIDE bl1 ? met links-rechts methode en "labda's" */
+ /* geeft als correct gat 1 terug */
+ BevPoint *bevp, *prevbevp;
+ float min,max,vec[3],hvec1[3],hvec2[3],lab,mu;
+ int nr, links=0,rechts=0,mode;
+
+ /* neem eerste vertex van het mogelijke gat */
+
+ bevp= (BevPoint *)(bl2+1);
+ hvec1[0]= bevp->x;
+ hvec1[1]= bevp->y;
+ hvec1[2]= 0.0;
+ VECCOPY(hvec2,hvec1);
+ hvec2[0]+=1000;
+
+ /* test deze met alle edges van mogelijk omringende poly */
+ /* tel aantal overgangen links en rechts */
+
+ bevp= (BevPoint *)(bl1+1);
+ nr= bl1->nr;
+ prevbevp= bevp+(nr-1);
+
+ while(nr--) {
+ min= prevbevp->y;
+ max= bevp->y;
+ if(max<min) {
+ min= max;
+ max= prevbevp->y;
+ }
+ if(min!=max) {
+ if(min<=hvec1[1] && max>=hvec1[1]) {
+ /* er is een overgang, snijpunt berekenen */
+ mode= cu_isectLL(&(prevbevp->x),&(bevp->x),hvec1,hvec2,0,1,&lab,&mu,vec);
+ /* als lab==0.0 of lab==1.0 dan snijdt de edge exact de overgang
+ * alleen toestaan voor lab= 1.0 (of andersom, maakt niet uit)
+ */
+ if(mode>=0 && lab!=0.0) {
+ if(vec[0]<hvec1[0]) links++;
+ else rechts++;
+ }
+ }
+ }
+ prevbevp= bevp;
+ bevp++;
+ }
+
+ if( (links & 1) && (rechts & 1) ) return 1;
+ return 0;
+}
+
+
+struct bevelsort {
+ float left;
+ BevList *bl;
+ int dir;
+};
+
+int vergxcobev(const void *a1, const void *a2)
+{
+ const struct bevelsort *x1=a1,*x2=a2;
+
+ if( x1->left > x2->left ) return 1;
+ else if( x1->left < x2->left) return -1;
+ return 0;
+}
+
+/* deze kan niet zomaar door atan2 vervangen worden, maar waarom? */
+
+void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *sina, float *cosa)
+{
+ float t01, t02, x3, y3;
+
+ t01= (float)sqrt(x1*x1+y1*y1);
+ t02= (float)sqrt(x2*x2+y2*y2);
+ if(t01==0.0) t01= 1.0;
+ if(t02==0.0) t02= 1.0;
+
+ x1/=t01;
+ y1/=t01;
+ x2/=t02;
+ y2/=t02;
+
+ t02= x1*x2+y1*y2;
+ if(fabs(t02)>=1.0) t02= .5*M_PI;
+ else t02= (saacos(t02))/2.0f;
+
+ t02= (float)sin(t02);
+ if(t02==0.0) t02= 1.0;
+
+ x3= x1-x2;
+ y3= y1-y2;
+ if(x3==0 && y3==0) {
+ /* printf("x3 en y3 nul \n"); */
+ x3= y1;
+ y3= -x1;
+ } else {
+ t01= (float)sqrt(x3*x3+y3*y3);
+ x3/=t01;
+ y3/=t01;
+ }
+
+ *sina= -y3/t02;
+ *cosa= x3/t02;
+
+}
+
+void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *data_a)
+{
+ BezTriple *pprev, *next, *last;
+ float fac, dfac, t[4];
+ int a;
+
+ last= nu->bezt+(nu->pntsu-1);
+
+ /* een punt terug */
+ if(prevbezt==nu->bezt) {
+ if(nu->flagu & 1) pprev= last;
+ else pprev= prevbezt;
+ }
+ else pprev= prevbezt-1;
+
+ /* een punt verder */
+ if(bezt==last) {
+ if(nu->flagu & 1) next= nu->bezt;
+ else next= bezt;
+ }
+ else next= bezt+1;
+
+ fac= 0.0;
+ dfac= 1.0f/(float)nu->resolu;
+
+ for(a=0; a<nu->resolu; a++, fac+= dfac) {
+
+ set_four_ipo(fac, t, KEY_BSPLINE);
+
+ data_a[a]= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa;
+ }
+}
+
+void makeBevelList(Object *ob)
+{
+ /* - alle curves omzetten in poly's, met aangegeven resol en vlaggen voor dubbele punten
+ - eventueel intelligent punten verwijderen (geval Nurb)
+ - scheiden in verschillende blokken met Boundbox
+ - Autogat detectie */
+ Curve *cu;
+ Nurb *nu;
+ BezTriple *bezt, *prevbezt;
+ BPoint *bp;
+ BevList *bl, *blnew, *blnext;
+ BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0;
+ float *data, *data_a, *v1, *v2, min, inp, x1, x2, y1, y2, vec[3];
+ struct bevelsort *sortdata, *sd, *sd1;
+ int a, b, len, nr, poly;
+
+ /* deze fie moet object hebben in verband met tflag en upflag */
+ cu= ob->data;
+
+ /* STAP 1: POLY'S MAKEN */
+
+ BLI_freelistN(&(cu->bev));
+ if(ob==G.obedit) nu= editNurb.first;
+ else nu= cu->nurb.first;
+
+ while(nu) {
+ if(nu->pntsu>1) {
+
+ if((nu->type & 7)==CU_POLY) {
+
+ len= nu->pntsu;
+ bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList");
+ BLI_addtail(&(cu->bev), bl);
+
+ if(nu->flagu & 1) bl->poly= 0;
+ else bl->poly= -1;
+ bl->nr= len;
+ bl->flag= 0;
+ bevp= (BevPoint *)(bl+1);
+ bp= nu->bp;
+
+ while(len--) {
+ bevp->x= bp->vec[0];
+ bevp->y= bp->vec[1];
+ bevp->z= bp->vec[2];
+ bevp->alfa= bp->alfa;
+ bevp->f1= 1;
+ bevp++;
+ bp++;
+ }
+ }
+ else if((nu->type & 7)==CU_BEZIER) {
+
+ len= nu->resolu*(nu->pntsu+ (nu->flagu & 1) -1)+1; /* voor laatste punt niet cyclic */
+ bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList");
+ BLI_addtail(&(cu->bev), bl);
+
+ if(nu->flagu & 1) bl->poly= 0;
+ else bl->poly= -1;
+ bevp= (BevPoint *)(bl+1);
+
+ a= nu->pntsu-1;
+ bezt= nu->bezt;
+ if(nu->flagu & 1) {
+ a++;
+ prevbezt= nu->bezt+(nu->pntsu-1);
+ }
+ else {
+ prevbezt= bezt;
+ bezt++;
+ }
+
+ data= MEM_mallocN(3*sizeof(float)*(nu->resolu+1), "makeBevelList2");
+ data_a= MEM_callocN(sizeof(float)*(nu->resolu+1), "data_a");
+
+ while(a--) {
+ if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) {
+
+ bevp->x= prevbezt->vec[1][0];
+ bevp->y= prevbezt->vec[1][1];
+ bevp->z= prevbezt->vec[1][2];
+ bevp->alfa= prevbezt->alfa;
+ bevp->f1= 1;
+ bevp->f2= 0;
+ bevp++;
+ bl->nr++;
+ bl->flag= 1;
+ }
+ else {
+ v1= prevbezt->vec[1];
+ v2= bezt->vec[0];
+
+ /* altijd alle drie doen: anders blijft data hangen */
+ maakbez(v1[0], v1[3], v2[0], v2[3], data, nu->resolu);
+ maakbez(v1[1], v1[4], v2[1], v2[4], data+1, nu->resolu);
+ maakbez(v1[2], v1[5], v2[2], v2[5], data+2, nu->resolu);
+
+ if((nu->type & CU_2D)==0) {
+ if(cu->flag & CU_3D) {
+ alfa_bezpart(prevbezt, bezt, nu, data_a);
+ }
+ }
+
+
+ /* met handlecodes dubbele punten aangeven */
+ if(prevbezt->h1==prevbezt->h2) {
+ if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= 1;
+ }
+ else {
+ if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= 1;
+ else if(prevbezt->h2==0 || prevbezt->h2==HD_VECT) bevp->f1= 1;
+ }
+
+ v1= data;
+ v2= data_a;
+ nr= nu->resolu;
+
+ while(nr--) {
+ bevp->x= v1[0];
+ bevp->y= v1[1];
+ bevp->z= v1[2];
+ bevp->alfa= v2[0];
+ bevp++;
+ v1+=3;
+ v2++;
+ }
+ bl->nr+= nu->resolu;
+
+ }
+ prevbezt= bezt;
+ bezt++;
+ }
+
+ MEM_freeN(data);
+ MEM_freeN(data_a);
+
+ if((nu->flagu & 1)==0) { /* niet cyclic: endpoint */
+ bevp->x= prevbezt->vec[1][0];
+ bevp->y= prevbezt->vec[1][1];
+ bevp->z= prevbezt->vec[1][2];
+ bl->nr++;
+ }
+
+ }
+ else if((nu->type & 7)==CU_NURBS) {
+ if(nu->pntsv==1) {
+ len= nu->resolu*nu->pntsu;
+ bl= MEM_mallocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList3");
+ BLI_addtail(&(cu->bev), bl);
+ bl->nr= len;
+ bl->flag= 0;
+ if(nu->flagu & 1) bl->poly= 0;
+ else bl->poly= -1;
+ bevp= (BevPoint *)(bl+1);
+
+ data= MEM_callocN(4*sizeof(float)*len, "makeBevelList4"); /* moet op nul staan */
+ makeNurbcurve(nu, data, 4);
+
+ v1= data;
+ while(len--) {
+ bevp->x= v1[0];
+ bevp->y= v1[1];
+ bevp->z= v1[2];
+ bevp->alfa= v1[3];
+
+ bevp->f1= bevp->f2= 0;
+ bevp++;
+ v1+=4;
+ }
+ MEM_freeN(data);
+ }
+ }
+ }
+ nu= nu->next;
+ }
+
+ /* STAP 2: DUBBELE PUNTEN EN AUTOMATISCHE RESOLUTIE, DATABLOKKEN VERKLEINEN */
+ bl= cu->bev.first;
+ while(bl) {
+ nr= bl->nr;
+ bevp1= (BevPoint *)(bl+1);
+ bevp0= bevp1+(nr-1);
+ nr--;
+ while(nr--) {
+ if( fabs(bevp0->x-bevp1->x)<0.00001 ) {
+ if( fabs(bevp0->y-bevp1->y)<0.00001 ) {
+ if( fabs(bevp0->z-bevp1->z)<0.00001 ) {
+ bevp0->f2= 1;
+ bl->flag++;
+ }
+ }
+ }
+ bevp0= bevp1;
+ bevp1++;
+ }
+ bl= bl->next;
+ }
+ bl= cu->bev.first;
+ while(bl) {
+ blnext= bl->next;
+ if(bl->flag) {
+ nr= bl->nr- bl->flag+1; /* +1 want vectorbezier zet ook flag */
+ blnew= MEM_mallocN(sizeof(BevList)+nr*sizeof(BevPoint), "makeBevelList");
+ memcpy(blnew, bl, sizeof(BevList));
+ blnew->nr= 0;
+ BLI_remlink(&(cu->bev), bl);
+ BLI_insertlinkbefore(&(cu->bev),blnext,blnew); /* zodat bevlijst met nurblijst gelijk loopt */
+ bevp0= (BevPoint *)(bl+1);
+ bevp1= (BevPoint *)(blnew+1);
+ nr= bl->nr;
+ while(nr--) {
+ if(bevp0->f2==0) {
+ memcpy(bevp1, bevp0, sizeof(BevPoint));
+ bevp1++;
+ blnew->nr++;
+ }
+ bevp0++;
+ }
+ MEM_freeN(bl);
+ blnew->flag= 0;
+ }
+ bl= blnext;
+ }
+
+ /* STAP 3: POLY'S TELLEN EN AUTOGAT */
+ bl= cu->bev.first;
+ poly= 0;
+ while(bl) {
+ if(bl->poly>=0) {
+ poly++;
+ bl->poly= poly;
+ bl->gat= 0;
+ }
+ bl= bl->next;
+ }
+
+
+ /* meest linkse punten vinden, tevens richting testen */
+ if(poly>0) {
+ sd= sortdata= MEM_mallocN(sizeof(struct bevelsort)*poly, "makeBevelList5");
+ bl= cu->bev.first;
+ while(bl) {
+ if(bl->poly>0) {
+
+ min= 300000.0;
+ bevp= (BevPoint *)(bl+1);
+ nr= bl->nr;
+ while(nr--) {
+ if(min>bevp->x) {
+ min= bevp->x;
+ bevp1= bevp;
+ }
+ bevp++;
+ }
+ sd->bl= bl;
+ sd->left= min;
+
+ bevp= (BevPoint *)(bl+1);
+ if(bevp1== bevp) bevp0= bevp+ (bl->nr-1);
+ else bevp0= bevp1-1;
+ bevp= bevp+ (bl->nr-1);
+ if(bevp1== bevp) bevp2= (BevPoint *)(bl+1);
+ else bevp2= bevp1+1;
+
+ inp= (bevp1->x- bevp0->x)*(bevp0->y- bevp2->y)
+ +(bevp0->y- bevp1->y)*(bevp0->x- bevp2->x);
+
+ if(inp>0.0) sd->dir= 1;
+ else sd->dir= 0;
+
+ sd++;
+ }
+
+ bl= bl->next;
+ }
+ qsort(sortdata,poly,sizeof(struct bevelsort), vergxcobev);
+
+ sd= sortdata+1;
+ for(a=1; a<poly; a++, sd++) {
+ bl= sd->bl; /* is bl een gat? */
+ sd1= sortdata+ (a-1);
+ for(b=a-1; b>=0; b--, sd1--) { /* alle polys links ervan */
+ if(bevelinside(sd1->bl, bl)) {
+ bl->gat= 1- sd1->bl->gat;
+ break;
+ }
+ }
+ }
+
+ /* draairichting */
+ if((cu->flag & CU_3D)==0) {
+ sd= sortdata;
+ for(a=0; a<poly; a++, sd++) {
+ if(sd->bl->gat==sd->dir) {
+ bl= sd->bl;
+ bevp1= (BevPoint *)(bl+1);
+ bevp2= bevp1+ (bl->nr-1);
+ nr= bl->nr/2;
+ while(nr--) {
+ SWAP(BevPoint, *bevp1, *bevp2);
+ bevp1++;
+ bevp2--;
+ }
+ }
+ }
+ }
+ MEM_freeN(sortdata);
+ }
+
+ /* STAP 4: COSINUSSEN */
+ bl= cu->bev.first;
+ while(bl) {
+
+ if(bl->nr==2) { /* 2 pnt, apart afhandelen: KAN DAT NIET AFGESCHAFT? */
+ bevp2= (BevPoint *)(bl+1);
+ bevp1= bevp2+1;
+
+ x1= bevp1->x- bevp2->x;
+ y1= bevp1->y- bevp2->y;
+
+ calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa));
+ bevp2->sina= bevp1->sina;
+ bevp2->cosa= bevp1->cosa;
+
+ if(cu->flag & CU_3D) { /* 3D */
+ float *quat, q[4];
+
+ vec[0]= bevp1->x - bevp2->x;
+ vec[1]= bevp1->y - bevp2->y;
+ vec[2]= bevp1->z - bevp2->z;
+
+ quat= vectoquat(vec, 5, 1);
+
+ Normalise(vec);
+ q[0]= (float)cos(0.5*bevp1->alfa);
+ x1= (float)sin(0.5*bevp1->alfa);
+ q[1]= x1*vec[0];
+ q[2]= x1*vec[1];
+ q[3]= x1*vec[2];
+ QuatMul(quat, q, quat);
+
+ QuatToMat3(quat, bevp1->mat);
+ Mat3CpyMat3(bevp2->mat, bevp1->mat);
+ }
+
+ }
+ else if(bl->nr>2) {
+ bevp2= (BevPoint *)(bl+1);
+ bevp1= bevp2+(bl->nr-1);
+ bevp0= bevp1-1;
+
+
+ nr= bl->nr;
+
+ while(nr--) {
+
+ if(cu->flag & CU_3D) { /* 3D */
+ float *quat, q[4];
+
+ vec[0]= bevp2->x - bevp0->x;
+ vec[1]= bevp2->y - bevp0->y;
+ vec[2]= bevp2->z - bevp0->z;
+
+ Normalise(vec);
+
+ quat= vectoquat(vec, 5, 1);
+
+ q[0]= (float)cos(0.5*bevp1->alfa);
+ x1= (float)sin(0.5*bevp1->alfa);
+ q[1]= x1*vec[0];
+ q[2]= x1*vec[1];
+ q[3]= x1*vec[2];
+ QuatMul(quat, q, quat);
+
+ QuatToMat3(quat, bevp1->mat);
+ }
+
+ x1= bevp1->x- bevp0->x;
+ x2= bevp1->x- bevp2->x;
+ y1= bevp1->y- bevp0->y;
+ y2= bevp1->y- bevp2->y;
+
+ calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa));
+
+
+ bevp0= bevp1;
+ bevp1= bevp2;
+ bevp2++;
+ }
+ /* niet cyclic gevallen corrigeren */
+ if(bl->poly== -1) {
+ if(bl->nr>2) {
+ bevp= (BevPoint *)(bl+1);
+ bevp1= bevp+1;
+ bevp->sina= bevp1->sina;
+ bevp->cosa= bevp1->cosa;
+ Mat3CpyMat3(bevp->mat, bevp1->mat);
+ bevp= (BevPoint *)(bl+1);
+ bevp+= (bl->nr-1);
+ bevp1= bevp-1;
+ bevp->sina= bevp1->sina;
+ bevp->cosa= bevp1->cosa;
+ Mat3CpyMat3(bevp->mat, bevp1->mat);
+ }
+ }
+ }
+ bl= bl->next;
+ }
+}
+
+/* ****************** HANDLES ************** */
+
+/*
+ * handlecodes:
+ * 1: niets, 1:auto, 2:vector, 3:aligned
+ */
+
+
+void calchandleNurb(BezTriple *bezt,BezTriple *prev, BezTriple *next, int mode)
+{
+ float *p1,*p2,*p3,pt[3];
+ float dx1,dy1,dz1,dx,dy,dz,vx,vy,vz,len,len1,len2;
+
+ if(bezt->h1==0 && bezt->h2==0) return;
+
+ p2= bezt->vec[1];
+
+ if(prev==0) {
+ p3= next->vec[1];
+ pt[0]= 2*p2[0]- p3[0];
+ pt[1]= 2*p2[1]- p3[1];
+ pt[2]= 2*p2[2]- p3[2];
+ p1= pt;
+ }
+ else p1= prev->vec[1];
+
+ if(next==0) {
+ pt[0]= 2*p2[0]- p1[0];
+ pt[1]= 2*p2[1]- p1[1];
+ pt[2]= 2*p2[2]- p1[2];
+ p3= pt;
+ }
+ else p3= next->vec[1];
+
+ if(mode && bezt->h1==HD_AUTO && prev) {
+ dx= p2[0] - (p1[0]+p1[3])/2.0f;
+ dy= p2[1] - (p1[1]+p1[4])/2.0f;
+ dz= p2[2] - (p1[2]+p1[5])/2.0f;
+ }
+ else {
+ dx= p2[0]- p1[0];
+ dy= p2[1]- p1[1];
+ dz= p2[2]- p1[2];
+ }
+ len1= (float)sqrt(dx*dx+dy*dy+dz*dz);
+
+ if(mode && bezt->h2==HD_AUTO && next) {
+ dx1= (p3[0]+p3[-3])/2.0f - p2[0];
+ dy1= (p3[1]+p3[-2])/2.0f - p2[1];
+ dz1= (p3[2]+p3[-1])/2.0f - p2[2];
+ }
+ else {
+ dx1= p3[0]- p2[0];
+ dy1= p3[1]- p2[1];
+ dz1= p3[2]- p2[2];
+ }
+ len2= (float)sqrt(dx1*dx1+dy1*dy1+dz1*dz1);
+
+ if(len1==0.0f) len1=1.0f;
+ if(len2==0.0f) len2=1.0f;
+
+
+ if(bezt->h1==HD_AUTO || bezt->h2==HD_AUTO) { /* auto */
+ vx= dx1/len2 + dx/len1;
+ vy= dy1/len2 + dy/len1;
+ vz= dz1/len2 + dz/len1;
+ len= 2.71f*(float)sqrt(vx*vx + vy*vy + vz*vz);
+ if(len!=0.0f) {
+
+ if(len1>5.0f*len2) len1= 5.0f*len2;
+ if(len2>5.0f*len1) len2= 5.0f*len1;
+
+ if(bezt->h1==HD_AUTO) {
+ len1/=len;
+ *(p2-3)= *p2-vx*len1;
+ *(p2-2)= *(p2+1)-vy*len1;
+ *(p2-1)= *(p2+2)-vz*len1;
+ }
+ if(bezt->h2==HD_AUTO) {
+ len2/=len;
+ *(p2+3)= *p2+vx*len2;
+ *(p2+4)= *(p2+1)+vy*len2;
+ *(p2+5)= *(p2+2)+vz*len2;
+ }
+ }
+ }
+
+ if(bezt->h1==HD_VECT) { /* vector */
+ dx/=3.0;
+ dy/=3.0;
+ dz/=3.0;
+ *(p2-3)= *p2-dx;
+ *(p2-2)= *(p2+1)-dy;
+ *(p2-1)= *(p2+2)-dz;
+ }
+ if(bezt->h2==HD_VECT) {
+ dx1/=3.0;
+ dy1/=3.0;
+ dz1/=3.0;
+ *(p2+3)= *p2+dx1;
+ *(p2+4)= *(p2+1)+dy1;
+ *(p2+5)= *(p2+2)+dz1;
+ }
+
+ len2= VecLenf(p2, p2+3);
+ len1= VecLenf(p2, p2-3);
+ if(len1==0.0) len1=1.0;
+ if(len2==0.0) len2=1.0;
+ if(bezt->f1 & 1) { /* volgorde van berekenen */
+ if(bezt->h2==HD_ALIGN) { /* aligned */
+ len= len2/len1;
+ p2[3]= p2[0]+len*(p2[0]-p2[-3]);
+ p2[4]= p2[1]+len*(p2[1]-p2[-2]);
+ p2[5]= p2[2]+len*(p2[2]-p2[-1]);
+ }
+ if(bezt->h1==HD_ALIGN) {
+ len= len1/len2;
+ p2[-3]= p2[0]+len*(p2[0]-p2[3]);
+ p2[-2]= p2[1]+len*(p2[1]-p2[4]);
+ p2[-1]= p2[2]+len*(p2[2]-p2[5]);
+ }
+ }
+ else {
+ if(bezt->h1==HD_ALIGN) {
+ len= len1/len2;
+ p2[-3]= p2[0]+len*(p2[0]-p2[3]);
+ p2[-2]= p2[1]+len*(p2[1]-p2[4]);
+ p2[-1]= p2[2]+len*(p2[2]-p2[5]);
+ }
+ if(bezt->h2==HD_ALIGN) { /* aligned */
+ len= len2/len1;
+ p2[3]= p2[0]+len*(p2[0]-p2[-3]);
+ p2[4]= p2[1]+len*(p2[1]-p2[-2]);
+ p2[5]= p2[2]+len*(p2[2]-p2[-1]);
+ }
+ }
+}
+
+void calchandlesNurb(Nurb *nu) /* wel eerst (zonodig) de handlevlaggen zetten */
+{
+ BezTriple *bezt, *prev, *next;
+ short a;
+
+ if((nu->type & 7)!=1) return;
+ if(nu->pntsu<2) return;
+
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ if(nu->flagu & 1) prev= bezt+(a-1);
+ else prev= 0;
+ next= bezt+1;
+
+ while(a--) {
+ calchandleNurb(bezt, prev, next, 0);
+ prev= bezt;
+ if(a==1) {
+ if(nu->flagu & 1) next= nu->bezt;
+ else next= 0;
+ }
+ else next++;
+
+ bezt++;
+ }
+}
+
+
+void testhandlesNurb(Nurb *nu)
+{
+ /* Te gebruiken als er iets an de handles is veranderd.
+ * Loopt alle BezTriples af met de volgende regels:
+ * FASE 1: types veranderen?
+ * Autocalchandles: worden ligned als NOT(000 || 111)
+ * Vectorhandles worden 'niets' als (selected en andere niet)
+ * FASE 2: handles herbereken
+ */
+ BezTriple *bezt;
+ short flag, a;
+
+ if((nu->type & 7)!=CU_BEZIER) return;
+
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ flag= 0;
+ if(bezt->f1 & 1) flag++;
+ if(bezt->f2 & 1) flag += 2;
+ if(bezt->f3 & 1) flag += 4;
+
+ if( !(flag==0 || flag==7) ) {
+ if(bezt->h1==HD_AUTO) { /* auto */
+ bezt->h1= HD_ALIGN;
+ }
+ if(bezt->h2==HD_AUTO) { /* auto */
+ bezt->h2= HD_ALIGN;
+ }
+
+ if(bezt->h1==HD_VECT) { /* vector */
+ if(flag < 4) bezt->h1= 0;
+ }
+ if(bezt->h2==HD_VECT) { /* vector */
+ if( flag > 3) bezt->h2= 0;
+ }
+ }
+ bezt++;
+ }
+
+ calchandlesNurb(nu);
+}
+
+void autocalchandlesNurb(Nurb *nu, int flag)
+{
+ /* Kijkt naar de coordinaten van de handles en berekent de soort */
+
+ BezTriple *bezt2, *bezt1, *bezt0;
+ int i, align, leftsmall, rightsmall;
+
+ if(nu==0 || nu->bezt==0) return;
+
+ bezt2 = nu->bezt;
+ bezt1 = bezt2 + (nu->pntsu-1);
+ bezt0 = bezt1 - 1;
+ i = nu->pntsu;
+
+ while(i--) {
+
+ align= leftsmall= rightsmall= 0;
+
+ /* linker handle: */
+ if(flag==0 || (bezt1->f1 & flag) ) {
+ bezt1->h1= 0;
+ /* afstand te klein: vectorhandle */
+ if( VecLenf( bezt1->vec[1], bezt0->vec[1] ) < 0.0001) {
+ bezt1->h1= HD_VECT;
+ leftsmall= 1;
+ }
+ else {
+ /* aligned handle? */
+ if(DistVL2Dfl(bezt1->vec[1], bezt1->vec[0], bezt1->vec[2]) < 0.0001) {
+ align= 1;
+ bezt1->h1= HD_ALIGN;
+ }
+ /* of toch vector handle? */
+ if(DistVL2Dfl(bezt1->vec[0], bezt1->vec[1], bezt0->vec[1]) < 0.0001)
+ bezt1->h1= HD_VECT;
+
+ }
+ }
+ /* rechter handle: */
+ if(flag==0 || (bezt1->f3 & flag) ) {
+ bezt1->h2= 0;
+ /* afstand te klein: vectorhandle */
+ if( VecLenf( bezt1->vec[1], bezt2->vec[1] ) < 0.0001) {
+ bezt1->h2= HD_VECT;
+ rightsmall= 1;
+ }
+ else {
+ /* aligned handle? */
+ if(align) bezt1->h2= HD_ALIGN;
+
+ /* of toch vector handle? */
+ if(DistVL2Dfl(bezt1->vec[2], bezt1->vec[1], bezt2->vec[1]) < 0.0001)
+ bezt1->h2= HD_VECT;
+
+ }
+ }
+ if(leftsmall && bezt1->h2==HD_ALIGN) bezt1->h2= 0;
+ if(rightsmall && bezt1->h1==HD_ALIGN) bezt1->h1= 0;
+
+ /* onzalige combinatie: */
+ if(bezt1->h1==HD_ALIGN && bezt1->h2==HD_VECT) bezt1->h1= 0;
+ if(bezt1->h2==HD_ALIGN && bezt1->h1==HD_VECT) bezt1->h2= 0;
+
+ bezt0= bezt1;
+ bezt1= bezt2;
+ bezt2++;
+ }
+
+ calchandlesNurb(nu);
+}
+
+void autocalchandlesNurb_all(int flag)
+{
+ Nurb *nu;
+
+ nu= editNurb.first;
+ while(nu) {
+ autocalchandlesNurb(nu, flag);
+ nu= nu->next;
+ }
+}
+
+void sethandlesNurb(short code)
+{
+ /* code==1: set autohandle */
+ /* code==2: set vectorhandle */
+ /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
+ Nurb *nu;
+ BezTriple *bezt;
+ short a, ok=0;
+
+ if(code==1 || code==2) {
+ nu= editNurb.first;
+ while(nu) {
+ if( (nu->type & 7)==1) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->f1 || bezt->f3) {
+ if(bezt->f1) bezt->h1= code;
+ if(bezt->f3) bezt->h2= code;
+ if(bezt->h1!=bezt->h2) {
+ if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
+ if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
+ }
+ }
+ bezt++;
+ }
+ calchandlesNurb(nu);
+ }
+ nu= nu->next;
+ }
+ }
+ else {
+ /* is er 1 handle NIET vrij: alles vrijmaken, else ALIGNED maken */
+
+ nu= editNurb.first;
+ while(nu) {
+ if( (nu->type & 7)==1) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->f1 && bezt->h1) ok= 1;
+ if(bezt->f3 && bezt->h2) ok= 1;
+ if(ok) break;
+ bezt++;
+ }
+ }
+ nu= nu->next;
+ }
+ if(ok) ok= HD_FREE;
+ else ok= HD_ALIGN;
+
+ nu= editNurb.first;
+ while(nu) {
+ if( (nu->type & 7)==1) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->f1) bezt->h1= ok;
+ if(bezt->f3 ) bezt->h2= ok;
+
+ bezt++;
+ }
+ calchandlesNurb(nu);
+ }
+ nu= nu->next;
+ }
+ }
+}
+
+void swapdata(void *adr1, void *adr2, int len)
+{
+
+ if(len<=0) return;
+
+ if(len<65) {
+ char adr[64];
+
+ memcpy(adr, adr1, len);
+ memcpy(adr1, adr2, len);
+ memcpy(adr2, adr, len);
+ }
+ else {
+ char *adr;
+
+ adr= (char *)malloc(len);
+ memcpy(adr, adr1, len);
+ memcpy(adr1, adr2, len);
+ memcpy(adr2, adr, len);
+ free(adr);
+ }
+}
+
+void switchdirectionNurb(Nurb *nu)
+{
+ BezTriple *bezt1, *bezt2;
+ BPoint *bp1, *bp2;
+ float *fp1, *fp2, *tempf;
+ int a, b;
+
+ if(nu->pntsu==1 && nu->pntsv==1) return;
+
+ if((nu->type & 7)==CU_BEZIER) {
+ a= nu->pntsu;
+ bezt1= nu->bezt;
+ bezt2= bezt1+(a-1);
+ if(a & 1) a+= 1; /* bij oneven ook van middelste inhoud swappen */
+ a/= 2;
+ while(a>0) {
+ if(bezt1!=bezt2) SWAP(BezTriple, *bezt1, *bezt2);
+
+ swapdata(bezt1->vec[0], bezt1->vec[2], 12);
+ if(bezt1!=bezt2) swapdata(bezt2->vec[0], bezt2->vec[2], 12);
+
+ SWAP(char, bezt1->h1, bezt1->h2);
+ SWAP(short, bezt1->f1, bezt1->f3);
+
+ if(bezt1!=bezt2) {
+ SWAP(char, bezt2->h1, bezt2->h2);
+ SWAP(short, bezt2->f1, bezt2->f3);
+ bezt1->alfa= -bezt1->alfa;
+ bezt2->alfa= -bezt2->alfa;
+ }
+ a--;
+ bezt1++;
+ bezt2--;
+ }
+ }
+ else if(nu->pntsv==1) {
+ a= nu->pntsu;
+ bp1= nu->bp;
+ bp2= bp1+(a-1);
+ a/= 2;
+ while(bp1!=bp2 && a>0) {
+ SWAP(BPoint, *bp1, *bp2);
+ a--;
+ bp1->alfa= -bp1->alfa;
+ bp2->alfa= -bp2->alfa;
+ bp1++;
+ bp2--;
+ }
+ if((nu->type & 7)==CU_NURBS) {
+ /* de knots omkeren */
+ a= KNOTSU(nu);
+ fp1= nu->knotsu;
+ fp2= fp1+(a-1);
+ a/= 2;
+ while(fp1!=fp2 && a>0) {
+ SWAP(float, *fp1, *fp2);
+ a--;
+ fp1++;
+ fp2--;
+ }
+ /* en weer in stijgende lijn maken */
+ a= KNOTSU(nu);
+ fp1= nu->knotsu;
+ fp2=tempf= MEM_mallocN(sizeof(float)*a, "switchdirect");
+ while(a--) {
+ fp2[0]= fabs(fp1[1]-fp1[0]);
+ fp1++;
+ fp2++;
+ }
+
+ a= KNOTSU(nu)-1;
+ fp1= nu->knotsu;
+ fp2= tempf;
+ fp1[0]= 0.0;
+ fp1++;
+ while(a--) {
+ fp1[0]= fp1[-1]+fp2[0];
+ fp1++;
+ fp2++;
+ }
+ MEM_freeN(tempf);
+ }
+ }
+ else {
+
+ for(b=0; b<nu->pntsv; b++) {
+
+ bp1= nu->bp+b*nu->pntsu;
+ a= nu->pntsu;
+ bp2= bp1+(a-1);
+ a/= 2;
+
+ while(bp1!=bp2 && a>0) {
+ SWAP(BPoint, *bp1, *bp2);
+ a--;
+ bp1++;
+ bp2--;
+ }
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
new file mode 100644
index 00000000000..76983001bb6
--- /dev/null
+++ b/source/blender/blenkernel/intern/deform.c
@@ -0,0 +1,120 @@
+/* deform.c June 2001
+ *
+ * support for deformation groups
+ *
+ * Reevan McKay
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_object_types.h"
+
+#include "BKE_deform.h"
+
+
+void color_temperature (float input, unsigned char *r, unsigned char *g, unsigned char *b)
+{
+
+ /* blue to red */
+
+ float fr = (float)(*r);
+ float fg = (float)(*g);
+ float fb = (float)(*b);
+
+ if (input < 0.0F)
+ input = 0.0F;
+
+ if (input > 1.0F)
+ input = 1.0F;
+
+ if (input<=0.25f){
+ fr=0.0f;
+ fg=255.0f * (input*4.0f);
+ fb=255.0f;
+ }
+ else if (input<=0.50f){
+ fr=0.0f;
+ fg=255.0f;
+ fb=255.0f * (1.0f-((input-0.25f)*4.0f));
+ }
+ else if (input<=0.75){
+ fr=255.0f * ((input-0.50f)*4.0f);
+ fg=255.0f;
+ fb=0.0f;
+ }
+ else if (input<=1.0){
+ fr=255.0f;
+ fg=255.0f * (1.0f-((input-0.75f)*4.0f));
+ fb=0.0f;
+ }
+
+ (*r) = (unsigned char)(fr * ((input/2.0f)+0.5f));
+ (*g) = (unsigned char)(fg * ((input/2.0f)+0.5f));
+ (*b) = (unsigned char)(fb * ((input/2.0f)+0.5f));
+
+
+};
+
+void copy_defgroups(ListBase *outbase, ListBase *inbase)
+{
+ bDeformGroup *defgroup, *defgroupn;
+
+ outbase->first= outbase->last= 0;
+
+ for (defgroup = inbase->first; defgroup; defgroup=defgroup->next){
+ defgroupn= copy_defgroup(defgroup);
+ BLI_addtail(outbase, defgroupn);
+ }
+}
+
+bDeformGroup* copy_defgroup (bDeformGroup *ingroup)
+{
+ bDeformGroup *outgroup;
+
+ if (!ingroup)
+ return NULL;
+
+ outgroup=MEM_callocN(sizeof(bDeformGroup), "deformGroup");
+
+ /* For now, just copy everything over. */
+ memcpy (outgroup, ingroup, sizeof(bDeformGroup));
+
+ outgroup->next=outgroup->prev=NULL;
+
+ return outgroup;
+}
+
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
new file mode 100644
index 00000000000..b9f9d59c5e3
--- /dev/null
+++ b/source/blender/blenkernel/intern/displist.c
@@ -0,0 +1,2085 @@
+
+/* displist.c GRAPHICS
+ *
+ *
+ * maart 95
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "nla.h" /* For __NLA: Please do not remove yet */
+
+#include "IMB_imbuf_types.h"
+
+#include "DNA_texture_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_listBase.h"
+#include "DNA_lamp_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_image_types.h"
+#include "DNA_material_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_lattice_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_displist.h"
+#include "BKE_object.h"
+#include "BKE_world.h"
+#include "BKE_mesh.h"
+#include "BKE_effect.h"
+#include "BKE_mball.h"
+#include "BKE_material.h"
+#include "BKE_curve.h"
+#include "BKE_anim.h"
+#include "BKE_screen.h"
+#include "BKE_texture.h"
+#include "BKE_library.h"
+#include "BKE_font.h"
+#include "BKE_lattice.h"
+#include "BKE_scene.h"
+#include "BKE_subsurf.h"
+
+/***/
+
+typedef struct _FastLamp FastLamp;
+struct _FastLamp {
+ FastLamp *next;
+
+ short type, mode, lay, rt;
+ float co[3];
+ float vec[3];
+ float dist, distkw, att1, att2, spotsi, spotbl, r, g, b;
+};
+
+/***/
+
+static FastLamp *fastlamplist= NULL;
+static float fviewmat[4][4];
+
+static void displistmesh_free(DispListMesh *dlm) {
+ // also check on mvert and mface, can be NULL after decimator (ton)
+ if( dlm->mvert) MEM_freeN(dlm->mvert);
+ if (dlm->mface) MEM_freeN(dlm->mface);
+ if (dlm->mcol) MEM_freeN(dlm->mcol);
+ if (dlm->tface) MEM_freeN(dlm->tface);
+ MEM_freeN(dlm);
+}
+
+static DispListMesh *displistmesh_copy(DispListMesh *odlm) {
+ DispListMesh *ndlm= MEM_dupallocN(odlm);
+ ndlm->mvert= MEM_dupallocN(odlm->mvert);
+ ndlm->mface= MEM_dupallocN(odlm->mface);
+ if (odlm->mcol) ndlm->mcol= MEM_dupallocN(odlm->mcol);
+ if (odlm->tface) ndlm->tface= MEM_dupallocN(odlm->tface);
+
+ return ndlm;
+}
+
+void free_disp_elem(DispList *dl)
+{
+ if(dl) {
+ if(dl->verts) MEM_freeN(dl->verts);
+ if(dl->nors) MEM_freeN(dl->nors);
+ if(dl->index) MEM_freeN(dl->index);
+ if(dl->col1) MEM_freeN(dl->col1);
+ if(dl->col2) MEM_freeN(dl->col2);
+ if(dl->mesh) displistmesh_free(dl->mesh);
+ MEM_freeN(dl);
+ }
+}
+
+void freedisplist(ListBase *lb)
+{
+ DispList *dl;
+
+ dl= lb->first;
+ while(dl) {
+ BLI_remlink(lb, dl);
+ free_disp_elem(dl);
+ dl= lb->first;
+ }
+}
+
+void free_displist_by_type(ListBase *lb, int type)
+{
+ DispList *dl;
+
+ for (dl= lb->first; dl; ) {
+ DispList *next= dl->next;
+
+ if (dl->type==type) {
+ BLI_remlink(lb, dl);
+ free_disp_elem(dl);
+ }
+
+ dl= next;
+ }
+}
+
+DispList *find_displist_create(ListBase *lb, int type)
+{
+ DispList *dl;
+
+ dl= lb->first;
+ while(dl) {
+ if(dl->type==type) return dl;
+ dl= dl->next;
+ }
+
+ dl= MEM_callocN(sizeof(DispList), "find_disp");
+ dl->type= type;
+ BLI_addtail(lb, dl);
+
+ return dl;
+}
+
+DispList *find_displist(ListBase *lb, int type)
+{
+ DispList *dl;
+
+ dl= lb->first;
+ while(dl) {
+ if(dl->type==type) return dl;
+ dl= dl->next;
+ }
+
+ return 0;
+}
+
+void copy_displist(ListBase *lbn, ListBase *lb)
+{
+ DispList *dln, *dl;
+
+ lbn->first= lbn->last= 0;
+
+ dl= lb->first;
+ while(dl) {
+
+ dln= MEM_dupallocN(dl);
+ BLI_addtail(lbn, dln);
+ dln->verts= MEM_dupallocN(dl->verts);
+ dln->nors= MEM_dupallocN(dl->nors);
+ dln->index= MEM_dupallocN(dl->index);
+ dln->col1= MEM_dupallocN(dl->col1);
+ dln->col2= MEM_dupallocN(dl->col2);
+ if (dl->mesh)
+ dln->mesh= displistmesh_copy(dl->mesh);
+
+ dl= dl->next;
+ }
+}
+
+static void initfastshade(void)
+{
+ Base *base;
+ Object *ob;
+ Lamp *la;
+ FastLamp *fl;
+ float mat[4][4];
+
+ R.vlr= 0;
+
+ init_render_world();
+
+ if(fastlamplist) return;
+ if(G.scene->camera==0) G.scene->camera= scene_find_camera(G.scene);
+ if(G.scene->camera==0) return;
+
+ /* uit roteerscene gejat */
+ where_is_object(G.scene->camera);
+ Mat4CpyMat4(R.viewinv, G.scene->camera->obmat);
+ Mat4Ortho(R.viewinv);
+ Mat4Invert(fviewmat, R.viewinv);
+
+
+ /* initrendertexture(); */
+
+ base= G.scene->base.first;
+ while(base) {
+ ob= base->object;
+ if( ob->type==OB_LAMP && (base->lay & G.scene->lay)) {
+
+ Mat4MulMat4(mat, ob->obmat, fviewmat);
+
+ la= ob->data;
+ fl= MEM_mallocN(sizeof(FastLamp), "initfastshade2");
+
+ fl->next= fastlamplist;
+ fastlamplist= fl;
+
+ fl->type= la->type;
+ fl->mode= la->mode;
+ fl->lay= base->lay;
+
+ fl->vec[0]= mat[2][0];
+ fl->vec[1]= mat[2][1];
+ fl->vec[2]= mat[2][2];
+ Normalise(fl->vec);
+
+ fl->co[0]= mat[3][0];
+ fl->co[1]= mat[3][1];
+ fl->co[2]= mat[3][2];
+
+ fl->dist= la->dist;
+ fl->distkw= fl->dist*fl->dist;
+ fl->att1= la->att1;
+ fl->att2= la->att2;
+
+ fl->spotsi= (float)cos( M_PI*la->spotsize/360.0 );
+ fl->spotbl= (1.0f-fl->spotsi)*la->spotblend;
+
+ fl->r= la->energy*la->r;
+ fl->g= la->energy*la->g;
+ fl->b= la->energy*la->b;
+ }
+
+ if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first;
+ else base= base->next;
+ }
+}
+
+
+void freefastshade()
+{
+ while (fastlamplist) {
+ FastLamp *fl= fastlamplist;
+ fastlamplist= fl->next;
+
+ MEM_freeN(fl);
+ }
+}
+
+
+static void fastshade(float *co, float *nor, float *orco, Material *ma, char *col1, char *col2, char *vertcol)
+{
+ FastLamp *fl;
+ float i, t, inp, soft, inpr, inpg, inpb, isr=0, isg=0, isb=0, lv[3], lampdist, ld;
+ float inpr1, inpg1, inpb1, isr1=0, isg1=0, isb1=0;
+ int a, back;
+
+ if(ma==0) return;
+ R.mat= ma;
+ R.matren= ma->ren;
+ ma= R.matren;
+
+ if(ma->mode & MA_VERTEXCOLP) {
+ if(vertcol) {
+ ma->r= vertcol[3]/255.0;
+ ma->g= vertcol[2]/255.0;
+ ma->b= vertcol[1]/255.0;
+ }
+ }
+
+ if(ma->texco) {
+ VECCOPY(R.lo, orco);
+ VECCOPY(R.vn, nor);
+
+ if(ma->texco & TEXCO_GLOB) {
+ VECCOPY(R.gl, R.lo);
+ }
+ if(ma->texco & TEXCO_WINDOW) {
+ VECCOPY(R.winco, R.lo);
+ }
+ if(ma->texco & TEXCO_STICKY) {
+ VECCOPY(R.sticky, R.lo);
+ }
+ if(ma->texco & TEXCO_UV) {
+ VECCOPY(R.uv, R.lo);
+ }
+ if(ma->texco & TEXCO_OBJECT) {
+ VECCOPY(R.co, R.lo);
+ }
+ if(ma->texco & TEXCO_NORM) {
+ VECCOPY(R.orn, R.vn);
+ }
+ if(ma->texco & TEXCO_REFL) {
+
+ inp= 2.0*(R.vn[2]);
+ R.ref[0]= (inp*R.vn[0]);
+ R.ref[1]= (inp*R.vn[1]);
+ R.ref[2]= (-1.0+inp*R.vn[2]);
+ }
+
+ if(ma->mode & MA_VERTEXCOLP) {
+ R.mat->r= ma->r;
+ R.mat->g= ma->g;
+ R.mat->b= ma->b;
+ }
+ do_material_tex();
+ }
+
+ if(ma->mode & MA_SHLESS) {
+ if(vertcol && (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) {
+ col1[3]= vertcol[3]*ma->r;
+ col1[2]= vertcol[2]*ma->g;
+ col1[1]= vertcol[1]*ma->b;
+ }
+ else {
+ col1[3]= (255.0*ma->r);
+ col1[2]= (255.0*ma->g);
+ col1[1]= (255.0*ma->b);
+ }
+ if(col2) {
+ col2[3]= col1[3];
+ col2[2]= col1[2];
+ col2[1]= col1[1];
+ }
+ return;
+ }
+
+ if( vertcol && (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) {
+ inpr= inpr1= ma->emit+vertcol[3]/255.0;
+ inpg= inpg1= ma->emit+vertcol[2]/255.0;
+ inpb= inpb1= ma->emit+vertcol[1]/255.0;
+ }
+ else {
+ inpr= inpg= inpb= inpr1= inpg1= inpb1= ma->emit;
+ }
+
+ /* col[0]= (255.0*ma->r); */
+ /* col[1]= (255.0*ma->g); */
+ /* col[2]= (255.0*ma->b); */
+
+ for (fl= fastlamplist; fl; fl= fl->next) {
+ /* if(fl->mode & LA_LAYER) if((fl->lay & ma->lay)==0) continue; */
+
+ if(fl->type==LA_SUN || fl->type==LA_HEMI) {
+ VECCOPY(lv, fl->vec);
+ lampdist= 1.0;
+ }
+ else {
+ lv[0]= fl->co[0] - co[0];
+ lv[1]= fl->co[1] - co[1];
+ lv[2]= fl->co[2] - co[2];
+ ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
+ lv[0]/=ld;
+ lv[1]/=ld;
+ lv[2]/=ld;
+
+ if(fl->mode & LA_QUAD) {
+ t= 1.0;
+ if(fl->att1>0.0)
+ t= fl->dist/(fl->dist+fl->att1*ld);
+ if(fl->att2>0.0)
+ t*= fl->distkw/(fl->distkw+fl->att2*ld*ld);
+
+ lampdist= t;
+ }
+ else {
+ lampdist= (fl->dist/(fl->dist+ld));
+ }
+
+ if(fl->mode & LA_SPHERE) {
+ t= fl->dist - ld;
+ if(t<0.0) continue;
+
+ t/= fl->dist;
+ lampdist*= (t);
+ }
+ }
+
+ if(fl->type==LA_SPOT) {
+ inp= lv[0]*fl->vec[0]+lv[1]*fl->vec[1]+lv[2]*fl->vec[2];
+ if(inp<fl->spotsi) continue;
+ else {
+ t= inp-fl->spotsi;
+ i= 1.0;
+ soft= 1.0;
+ if(t<fl->spotbl && fl->spotbl!=0.0) {
+ /* zachte gebied */
+ i= t/fl->spotbl;
+ t= i*i;
+ soft= (3.0*t-2.0*t*i);
+ inp*= soft;
+ }
+
+ lampdist*=inp;
+ }
+ }
+
+ inp= nor[0]*lv[0]+ nor[1]*lv[1]+ nor[2]*lv[2];
+
+ back= 0;
+ if(inp<0.0) {
+ back= 1;
+ inp= -inp;
+ }
+ inp*= lampdist*ma->ref;
+
+ if(back==0) {
+ inpr+= inp*fl->r;
+ inpg+= inp*fl->g;
+ inpb+= inp*fl->b;
+ } else if(col2) {
+ inpr1+= inp*fl->r;
+ inpg1+= inp*fl->g;
+ inpb1+= inp*fl->b;
+ }
+ if(ma->spec) {
+
+ lv[2]+= 1.0;
+ Normalise(lv);
+ t= nor[0]*lv[0]+nor[1]*lv[1]+nor[2]*lv[2];
+ if(t>0) {
+ t= ma->spec*lampdist*RE_Spec(t, ma->har);
+ if(back==0) {
+ isr+= t*(fl->r * ma->specr);
+ isg+= t*(fl->g * ma->specg);
+ isb+= t*(fl->b * ma->specb);
+ }
+ else if(col2) {
+ isr1+= t*(fl->r * ma->specr);
+ isg1+= t*(fl->g * ma->specg);
+ isb1+= t*(fl->b * ma->specb);
+ }
+ }
+ }
+
+ }
+
+ a= 256*(inpr*ma->r + ma->ambr +isr);
+ if(a>255) col1[3]= 255;
+ else col1[3]= a;
+ a= 256*(inpg*ma->g + ma->ambg +isg);
+ if(a>255) col1[2]= 255;
+ else col1[2]= a;
+ a= 256*(inpb*ma->b + ma->ambb +isb);
+ if(a>255) col1[1]= 255;
+ else col1[1]= a;
+
+ if(col2) {
+ a= 256*(inpr1*ma->r + ma->ambr +isr1);
+ if(a>255) col2[3]= 255;
+ else col2[3]= a;
+ a= 256*(inpr1*ma->g + ma->ambg +isg1);
+ if(a>255) col2[2]= 255;
+ else col2[2]= a;
+ a= 256*(inpr1*ma->b + ma->ambb +isb1);
+ if(a>255) col2[1]= 255;
+ else col2[1]= a;
+ }
+
+}
+
+void addnormalsDispList(Object *ob, ListBase *lb)
+{
+ DispList *dl = NULL;
+ Mesh *me;
+ MVert *ve1, *ve2, *ve3, *ve4;
+ MFace *mface;
+ float *vdata, *ndata, nor[3];
+ float *v1, *v2, *v3, *v4;
+ float *n1, *n2, *n3, *n4;
+ int a, b, p1, p2, p3, p4;
+
+
+ if(ob->type==OB_MESH) {
+
+ me= get_mesh(ob);
+
+ if (mesh_uses_displist(me)) {
+ DispList *dl= find_displist(&me->disp, DL_MESH);
+
+ if (dl && !dl->nors) {
+ DispListMesh *dlm= dl->mesh;
+ int i;
+
+ dl->nors= MEM_mallocN(sizeof(*dl->nors)*3*dlm->totface, "meshnormals");
+
+ for (i=0; i<dlm->totface; i++) {
+ MFaceInt *mf= &dlm->mface[i];
+ float *no= &dl->nors[i*3];
+
+ if (mf->v3) {
+ if (mf->v4)
+ CalcNormFloat4(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, dlm->mvert[mf->v4].co, no);
+ else
+ CalcNormFloat(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, no);
+ }
+ }
+ }
+ } else {
+ if(me->totface==0) return;
+
+ if(me->disp.first==0) {
+ dl= MEM_callocN(sizeof(DispList), "meshdisp");
+ dl->type= DL_NORS;
+ dl->parts= 1;
+ dl->nr= me->totface;
+ BLI_addtail(&me->disp, dl);
+ }
+
+ if(dl->nors==0) {
+ dl->nors= MEM_mallocN(sizeof(float)*3*me->totface, "meshnormals");
+ n1= dl->nors;
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+ if(mface->v3) {
+ ve1= me->mvert+mface->v1;
+ ve2= me->mvert+mface->v2;
+ ve3= me->mvert+mface->v3;
+ ve4= me->mvert+mface->v4;
+
+ if(mface->v4) CalcNormFloat4(ve1->co, ve2->co, ve3->co, ve4->co, n1);
+ else CalcNormFloat(ve1->co, ve2->co, ve3->co, n1);
+ }
+ n1+= 3;
+ mface++;
+ }
+ }
+ }
+
+ return;
+ }
+
+ dl= lb->first;
+
+ while(dl) {
+ if(dl->type==DL_INDEX3) {
+ if(dl->nors==0) {
+ dl->nors= MEM_callocN(sizeof(float)*3, "dlnors");
+ if(dl->verts[2]<0.0) dl->nors[2]= -1.0;
+ else dl->nors[2]= 1.0;
+ }
+ }
+ else if(dl->type==DL_SURF) {
+ if(dl->nors==0) {
+ dl->nors= MEM_callocN(sizeof(float)*3*dl->nr*dl->parts, "dlnors");
+
+ vdata= dl->verts;
+ ndata= dl->nors;
+
+ for(a=0; a<dl->parts; a++) {
+
+ DL_SURFINDEX(dl->flag & 1, dl->flag & 2, dl->nr, dl->parts);
+
+ v1= vdata+ 3*p1;
+ n1= ndata+ 3*p1;
+ v2= vdata+ 3*p2;
+ n2= ndata+ 3*p2;
+ v3= vdata+ 3*p3;
+ n3= ndata+ 3*p3;
+ v4= vdata+ 3*p4;
+ n4= ndata+ 3*p4;
+
+ for(; b<dl->nr; b++) {
+
+ CalcNormFloat4(v1, v3, v4, v2, nor);
+
+ VecAddf(n1, n1, nor);
+ VecAddf(n2, n2, nor);
+ VecAddf(n3, n3, nor);
+ VecAddf(n4, n4, nor);
+
+ v2= v1; v1+= 3;
+ v4= v3; v3+= 3;
+ n2= n1; n1+= 3;
+ n4= n3; n3+= 3;
+ }
+ }
+ a= dl->parts*dl->nr;
+ v1= ndata;
+ while(a--) {
+ Normalise(v1);
+ v1+= 3;
+ }
+ }
+ }
+ dl= dl->next;
+ }
+}
+
+
+void shadeDispList(Object *ob)
+{
+ MFace *mface;
+ MVert *mvert;
+ DispList *dl, *dlob, *dldeform;
+ Material *ma = NULL;
+ Mesh *me;
+ Curve *cu;
+/* extern Material defmaterial; *//* initrender.c, already in bad lev calls*/
+ float *orco, imat[3][3], tmat[4][4], mat[4][4], vec[3], xn, yn, zn;
+ float *fp, *nor, n1[3];
+ unsigned int *col1, *col2, *vertcol;
+ int a, lastmat= -1, need_orco = 0;
+
+ if(ob->flag & OB_FROMDUPLI) return;
+ initfastshade();
+
+ Mat4MulMat4(mat, ob->obmat, fviewmat);
+
+ Mat4Invert(tmat, mat);
+ Mat3CpyMat4(imat, tmat);
+
+ /* we halen de dl_verts eruit, deform info */
+ dldeform= find_displist(&ob->disp, DL_VERTS);
+ if(dldeform) BLI_remlink(&ob->disp, dldeform);
+
+ /* Metaballs hebben de standaard displist aan het Object zitten */
+ if(ob->type!=OB_MBALL) freedisplist(&ob->disp);
+
+ if((R.flag & R_RENDERING)==0) {
+ need_orco= 0;
+ for(a=0; a<ob->totcol; a++) {
+ ma= give_current_material(ob, a+1);
+ if(ma) {
+ init_render_material(ma);
+ if(ma->ren->texco & TEXCO_ORCO) need_orco= 1;
+ }
+ }
+ }
+ if(ob->type==OB_MESH) {
+
+ me= ob->data;
+
+ if (mesh_uses_displist(me)) {
+ if (need_orco) {
+ make_orco_displist_mesh(ob, me->subdiv);
+ orco= me->orco;
+ }
+
+ dl= me->disp.first;
+ while(dl) {
+ if(dl->type==DL_MESH) {
+ DispListMesh *dlm= dl->mesh;
+ int i;
+
+ dlob= MEM_callocN(sizeof(DispList), "displistshade");
+ BLI_addtail(&ob->disp, dlob);
+ dlob->type= DL_VERTCOL;
+
+ dlob->col1= MEM_mallocN(sizeof(*dlob->col1)*dlm->totface*4, "col1");
+ if (me->flag & ME_TWOSIDED)
+ dlob->col2= MEM_mallocN(sizeof(*dlob->col2)*dlm->totface*4, "col1");
+
+ for (i=0; i<dlm->totface; i++) {
+ MFaceInt *mf= &dlm->mface[i];
+
+ if (mf->v3) {
+ int j, vidx[4], nverts= mf->v4?4:3;
+ unsigned int *col1base= &dlob->col1[i*4];
+ unsigned int *col2base= dlob->col2?&dlob->col2[i*4]:NULL;
+ MCol *mcolbase= dlm->mcol?&dlm->mcol[i*4]:NULL;
+ float nor[3];
+
+ ma= give_current_material(ob, mf->mat_nr+1);
+ if(ma==0) ma= &defmaterial;
+
+ vidx[0]= mf->v1;
+ vidx[1]= mf->v2;
+ vidx[2]= mf->v3;
+ vidx[3]= mf->v4;
+
+ if (mf->v4)
+ CalcNormFloat4(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, dlm->mvert[mf->v4].co, nor);
+ else
+ CalcNormFloat(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, nor);
+
+ n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
+ n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
+ n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
+ Normalise(n1);
+
+ for (j=0; j<nverts; j++) {
+ MVert *mv= &dlm->mvert[vidx[j]];
+ unsigned int *col1= &col1base[j];
+ unsigned int *col2= col2base?&col2base[j]:NULL;
+ MCol *mcol= mcolbase?&mcolbase[j]:NULL;
+
+ VECCOPY(vec, mv->co);
+ Mat4MulVecfl(mat, vec);
+
+ if (need_orco && orco)
+ fastshade(vec, n1, &orco[vidx[j]*3], ma, (char *)col1, (char*)col2, (char*) mcol);
+ else
+ fastshade(vec, n1, mv->co, ma, (char *)col1, (char*)col2, (char*) mcol);
+ }
+ }
+ }
+ }
+ dl= dl->next;
+ }
+
+ if (need_orco && orco) {
+ MEM_freeN(me->orco);
+ me->orco= NULL;
+ }
+ }
+ else if(me->totvert>0) {
+
+ if(me->orco==0 && need_orco) {
+ make_orco_mesh(me);
+ }
+ orco= me->orco;
+ /* ms= me->msticky; */
+
+ dl= me->disp.first;
+ if(dl==0 || dl->nors==0) addnormalsDispList(ob, &me->disp);
+ dl= me->disp.first;
+ if(dl==0 || dl->nors==0) return;
+ nor= dl->nors;
+
+ dl= MEM_callocN(sizeof(DispList), "displistshade");
+ BLI_addtail(&ob->disp, dl);
+ dl->type= DL_VERTCOL;
+ col1= dl->col1= MEM_mallocN(4*sizeof(int)*me->totface, "col1");
+ col2= 0;
+ if(me->tface) tface_to_mcol(me);
+ vertcol= (unsigned int *)me->mcol;
+
+ if( me->flag & ME_TWOSIDED) {
+ col2= dl->col2= MEM_mallocN(4*sizeof(int)*me->totface, "col2");
+ }
+
+ /* even geen puno's */
+ mvert= me->mvert;
+ a= me->totvert;
+ while(FALSE || a--) {
+
+ VECCOPY(vec, mvert->co);
+ Mat4MulVecfl(mat, vec);
+
+ xn= mvert->no[0];
+ yn= mvert->no[1];
+ zn= mvert->no[2];
+
+ /* transpose ! */
+ n1[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+ n1[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+ n1[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+ Normalise(n1);
+
+ mvert++;
+ }
+
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+
+ if(mface->v3) {
+
+ /* transpose ! */
+ n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
+ n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
+ n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
+ Normalise(n1);
+
+ if(lastmat!=mface->mat_nr) {
+ ma= give_current_material(ob, mface->mat_nr+1);
+ if(ma==0) ma= &defmaterial;
+ lastmat= mface->mat_nr;
+ }
+
+ mvert= me->mvert+mface->v1;
+ VECCOPY(vec, mvert->co);
+ Mat4MulVecfl(mat, vec);
+
+ if(orco) fastshade(vec, n1, orco+3*mface->v1, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ col1++;
+ if(vertcol) vertcol++;
+ if(col2) col2++;
+
+ mvert= me->mvert+mface->v2;
+ VECCOPY(vec, mvert->co);
+ Mat4MulVecfl(mat, vec);
+
+ if(orco) fastshade(vec, n1, orco+3*mface->v2, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ col1++;
+ if(vertcol) vertcol++;
+ if(col2) col2++;
+
+ mvert= me->mvert+mface->v3;
+ VECCOPY(vec, mvert->co);
+ Mat4MulVecfl(mat, vec);
+
+ if(orco) fastshade(vec, n1, orco+3*mface->v3, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ col1++;
+ if(vertcol) vertcol++;
+ if(col2) col2++;
+
+ if(mface->v4) {
+ mvert= me->mvert+mface->v4;
+ VECCOPY(vec, mvert->co);
+ Mat4MulVecfl(mat, vec);
+
+ if(orco) fastshade(vec, n1, orco+3*mface->v4, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ }
+ col1++;
+ if(vertcol) vertcol++;
+ if(col2) col2++;
+
+ }
+ else {
+ col1+=4;
+ if(vertcol) vertcol+=4;
+ if(col2) col2+=4;
+ }
+
+ nor+= 3;
+ mface++;
+ }
+
+ if(me->orco) {
+ MEM_freeN(me->orco);
+ me->orco= 0;
+ }
+ if(me->tface) {
+ MEM_freeN(me->mcol);
+ me->mcol= 0;
+ }
+ }
+ }
+ else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
+
+ /* nu hebben we wel de normalen nodig */
+ cu= ob->data;
+ dl= cu->disp.first;
+
+ while(dl) {
+ dlob= MEM_callocN(sizeof(DispList), "displistshade");
+ BLI_addtail(&ob->disp, dlob);
+ dlob->type= DL_VERTCOL;
+ dlob->parts= dl->parts;
+ dlob->nr= dl->nr;
+
+ if(dl->type==DL_INDEX3) {
+ col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1");
+ }
+ else {
+ col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->parts*dl->nr, "col1");
+ }
+
+
+ ma= give_current_material(ob, dl->col+1);
+ if(ma==0) ma= &defmaterial;
+
+ if(dl->type==DL_INDEX3) {
+ if(dl->nors) {
+ /* er is maar 1 normaal */
+ n1[0]= imat[0][0]*dl->nors[0]+imat[0][1]*dl->nors[1]+imat[0][2]*dl->nors[2];
+ n1[1]= imat[1][0]*dl->nors[0]+imat[1][1]*dl->nors[1]+imat[1][2]*dl->nors[2];
+ n1[2]= imat[2][0]*dl->nors[0]+imat[2][1]*dl->nors[1]+imat[2][2]*dl->nors[2];
+ Normalise(n1);
+
+ fp= dl->verts;
+
+ a= dl->nr;
+ while(a--) {
+ VECCOPY(vec, fp);
+ Mat4MulVecfl(mat, vec);
+
+ fastshade(vec, n1, fp, ma, (char *)col1, 0, 0);
+
+ fp+= 3; col1++;
+ }
+ }
+ }
+ else if(dl->type==DL_SURF) {
+ if(dl->nors) {
+ a= dl->nr*dl->parts;
+ fp= dl->verts;
+ nor= dl->nors;
+
+ while(a--) {
+ VECCOPY(vec, fp);
+ Mat4MulVecfl(mat, vec);
+
+ n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
+ n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
+ n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
+ Normalise(n1);
+
+ fastshade(vec, n1, fp, ma, (char *)col1, 0, 0);
+
+ fp+= 3; nor+= 3; col1++;
+ }
+ }
+ }
+ dl= dl->next;
+ }
+ }
+ else if(ob->type==OB_MBALL) {
+ /* normalen zijn er al */
+ dl= ob->disp.first;
+
+ while(dl) {
+
+ if(dl->type==DL_INDEX4) {
+ if(dl->nors) {
+
+ if(dl->col1) MEM_freeN(dl->col1);
+ col1= dl->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1");
+
+ ma= give_current_material(ob, dl->col+1);
+ if(ma==0) ma= &defmaterial;
+
+ fp= dl->verts;
+ nor= dl->nors;
+
+ a= dl->nr;
+ while(a--) {
+ VECCOPY(vec, fp);
+ Mat4MulVecfl(mat, vec);
+
+ /* transpose ! */
+ n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
+ n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
+ n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
+ Normalise(n1);
+
+ fastshade(vec, n1, fp, ma, (char *)col1, 0, 0);
+
+ fp+= 3; col1++; nor+= 3;
+ }
+ }
+ }
+ dl= dl->next;
+ }
+ }
+
+ if((R.flag & R_RENDERING)==0) {
+ for(a=0; a<ob->totcol; a++) {
+ ma= give_current_material(ob, a+1);
+ if(ma) end_render_material(ma);
+ }
+ }
+
+ /* deze was er tijdelijk uitgehaald */
+ if(dldeform) BLI_addtail(&ob->disp, dldeform);
+}
+
+void reshadeall_displist(void)
+{
+ DispList *dldeform;
+ Base *base;
+ Object *ob;
+
+ freefastshade();
+
+ base= G.scene->base.first;
+ while(base) {
+ if(base->lay & G.scene->lay) {
+
+ ob= base->object;
+
+ /* we halen de dl_verts eruit, deform info */
+ dldeform= find_displist(&ob->disp, DL_VERTS);
+ if(dldeform) BLI_remlink(&ob->disp, dldeform);
+
+ /* Metaballs hebben de standaard displist aan het Object zitten */
+ if(ob->type==OB_MBALL) shadeDispList(ob);
+ else freedisplist(&ob->disp);
+
+ if(dldeform) BLI_addtail(&ob->disp, dldeform);
+ }
+ base= base->next;
+ }
+}
+
+void count_displist(ListBase *lb, int *totvert, int *totface)
+{
+ DispList *dl;
+
+ dl= lb->first;
+ while(dl) {
+
+ switch(dl->type) {
+ case DL_SURF:
+ *totvert+= dl->nr*dl->parts;
+ *totface+= (dl->nr-1)*(dl->parts-1);
+ break;
+ case DL_INDEX3:
+ case DL_INDEX4:
+ *totvert+= dl->nr;
+ *totface+= dl->parts;
+ break;
+ case DL_POLY:
+ case DL_SEGM:
+ *totvert+= dl->nr*dl->parts;
+ }
+
+ dl= dl->next;
+ }
+}
+
+static void curve_to_displist(ListBase *nubase, ListBase *dispbase)
+{
+ Nurb *nu;
+ DispList *dl;
+ BezTriple *bezt, *prevbezt;
+ BPoint *bp;
+ float *data, *v1, *v2;
+ int a, len;
+
+ nu= nubase->first;
+
+ while(nu) {
+ if(nu->hide==0) {
+ if((nu->type & 7)==CU_BEZIER) {
+
+ /* tellen */
+ len= 0;
+ a= nu->pntsu-1;
+ if(nu->flagu & 1) a++;
+
+ prevbezt= nu->bezt;
+ bezt= prevbezt+1;
+ while(a--) {
+ if(a==0 && (nu->flagu & 1)) bezt= nu->bezt;
+
+ if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) len++;
+ else len+= nu->resolu;
+
+ if(a==0 && (nu->flagu & 1)==0) len++;
+
+ prevbezt= bezt;
+ bezt++;
+ }
+
+ dl= MEM_callocN(sizeof(DispList), "makeDispListbez");
+ /* len+1 i.v.m. maakbez */
+ dl->verts= MEM_callocN( (len+1)*3*sizeof(float), "dlverts");
+ BLI_addtail(dispbase, dl);
+ dl->parts= 1;
+ dl->nr= len;
+ dl->col= nu->mat_nr;
+
+ data= dl->verts;
+
+ if(nu->flagu & 1) {
+ dl->type= DL_POLY;
+ a= nu->pntsu;
+ }
+ else {
+ dl->type= DL_SEGM;
+ a= nu->pntsu-1;
+ }
+
+ prevbezt= nu->bezt;
+ bezt= prevbezt+1;
+
+ while(a--) {
+ if(a==0 && dl->type== DL_POLY) bezt= nu->bezt;
+
+ if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) {
+ VECCOPY(data, prevbezt->vec[1]);
+ data+= 3;
+ }
+ else {
+ v1= prevbezt->vec[1];
+ v2= bezt->vec[0];
+ maakbez(v1[0], v1[3], v2[0], v2[3], data, nu->resolu);
+ maakbez(v1[1], v1[4], v2[1], v2[4], data+1, nu->resolu);
+ if((nu->type & 8)==0)
+ maakbez(v1[2], v1[5], v2[2], v2[5], data+2, nu->resolu);
+ data+= 3*nu->resolu;
+ }
+
+ if(a==0 && dl->type==DL_SEGM) {
+ VECCOPY(data, bezt->vec[1]);
+ }
+
+ prevbezt= bezt;
+ bezt++;
+ }
+ }
+ else if((nu->type & 7)==CU_NURBS) {
+ len= nu->pntsu*nu->resolu;
+ dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
+ dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
+ BLI_addtail(dispbase, dl);
+ dl->parts= 1;
+ dl->nr= len;
+ dl->col= nu->mat_nr;
+
+ data= dl->verts;
+ if(nu->flagu & 1) dl->type= DL_POLY;
+ else dl->type= DL_SEGM;
+ makeNurbcurve(nu, data, 3);
+ }
+ else if((nu->type & 7)==CU_POLY) {
+ len= nu->pntsu;
+ dl= MEM_callocN(sizeof(DispList), "makeDispListpoly");
+ dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
+ BLI_addtail(dispbase, dl);
+ dl->parts= 1;
+ dl->nr= len;
+ dl->col= nu->mat_nr;
+
+ data= dl->verts;
+ if(nu->flagu & 1) dl->type= DL_POLY;
+ else dl->type= DL_SEGM;
+
+ a= len;
+ bp= nu->bp;
+ while(a--) {
+ VECCOPY(data, bp->vec);
+ bp++;
+ data+= 3;
+ }
+ }
+ }
+ nu= nu->next;
+ }
+}
+
+
+static void filldisplist(ListBase *dispbase, ListBase *to)
+{
+ EditVert *eve, *v1, *vlast;
+ EditVlak *evl;
+ DispList *dlnew=0, *dl;
+ float *f1;
+ int colnr=0, cont=1, tot, a, *index;
+ long totvert;
+
+ if(dispbase==0) return;
+ if(dispbase->first==0) return;
+
+ /* tijd= clock(); */
+ /* bit-wise and comes after == .... so this doesn't work... */
+/* if(G.f & G_PLAYANIM == 0) waitcursor(1); */
+ if( !(G.f & G_PLAYANIM) ) waitcursor(1);
+
+ while(cont) {
+ cont= 0;
+ totvert=0;
+
+ dl= dispbase->first;
+ while(dl) {
+
+ if(dl->type==DL_POLY) {
+ if(colnr<dl->col) cont= 1;
+ else if(colnr==dl->col) {
+
+ colnr= dl->col;
+
+ /* editverts en edges maken */
+ f1= dl->verts;
+ a= dl->nr;
+ eve= v1= 0;
+
+ while(a--) {
+ vlast= eve;
+
+ eve= BLI_addfillvert(f1);
+ totvert++;
+
+ if(vlast==0) v1= eve;
+ else {
+ BLI_addfilledge(vlast, eve);
+ }
+ f1+=3;
+ }
+
+ if(eve!=0 && v1!=0) {
+ BLI_addfilledge(eve, v1);
+ }
+ }
+ }
+ dl= dl->next;
+ }
+
+ /* to make edgefill work
+ G.obedit can be 0 on file load */
+ if (G.obedit) {
+ BLI_setScanFillObjectRef(G.obedit);
+ BLI_setScanFillColourRef(&G.obedit->actcol);
+ }
+
+ if(totvert && BLI_edgefill(0)!=0) {
+
+ /* vlakken tellen */
+ tot= 0;
+ evl= fillvlakbase.first;
+ while(evl) {
+ tot++;
+ evl= evl->next;
+ }
+
+ if(tot) {
+ dlnew= MEM_callocN(sizeof(DispList), "filldisplist");
+ dlnew->type= DL_INDEX3;
+ dlnew->col= colnr;
+ dlnew->nr= totvert;
+ dlnew->parts= tot;
+
+ dlnew->index= MEM_mallocN(tot*3*sizeof(int), "dlindex");
+ dlnew->verts= MEM_mallocN(totvert*3*sizeof(float), "dlverts");
+
+ /* vertdata */
+ f1= dlnew->verts;
+ totvert= 0;
+ eve= fillvertbase.first;
+ while(eve) {
+ VECCOPY(f1, eve->co);
+ f1+= 3;
+
+ /* indexnummer */
+ eve->vn= (EditVert *)totvert;
+ totvert++;
+
+ eve= eve->next;
+ }
+
+ /* indexdata */
+ evl= fillvlakbase.first;
+ index= dlnew->index;
+ while(evl) {
+ index[0]= (long)evl->v1->vn;
+ index[1]= (long)evl->v2->vn;
+ index[2]= (long)evl->v3->vn;
+
+ index+= 3;
+ evl= evl->next;
+ }
+ }
+
+ BLI_addhead(to, dlnew);
+
+ }
+ BLI_end_edgefill();
+
+ colnr++;
+ }
+
+ /* poly's niet vrijgeven. nodig voor wireframe display */
+
+ /* same as above ... */
+/* if(G.f & G_PLAYANIM == 0) waitcursor(0); */
+ if( !(G.f & G_PLAYANIM) ) waitcursor(0);
+ /* printf("time: %d\n",(clock()-tijd)/1000); */
+
+}
+
+static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
+{
+ ListBase front, back;
+ DispList *dl, *dlnew;
+ float *fp, *fp1;
+ int a, dpoly;
+
+ front.first= front.last= back.first= back.last= 0;
+
+ if(cu->flag & CU_3D) return;
+ if( (cu->flag & (CU_FRONT+CU_BACK))==0 ) return;
+
+ dl= dispbase->first;
+ while(dl) {
+ if(dl->type==DL_SURF) {
+ if(dl->flag==2) {
+ if(cu->flag & CU_BACK) {
+ dlnew= MEM_callocN(sizeof(DispList), "filldisp");
+ BLI_addtail(&front, dlnew);
+ dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
+ dlnew->nr= dl->parts;
+ dlnew->parts= 1;
+ dlnew->type= DL_POLY;
+ dlnew->col= dl->col;
+
+ fp= dl->verts;
+ dpoly= 3*dl->nr;
+
+ a= dl->parts;
+ while(a--) {
+ VECCOPY(fp1, fp);
+ fp1+= 3;
+ fp+= dpoly;
+ }
+ }
+ if(cu->flag & CU_FRONT) {
+ dlnew= MEM_callocN(sizeof(DispList), "filldisp");
+ BLI_addtail(&back, dlnew);
+ dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
+ dlnew->nr= dl->parts;
+ dlnew->parts= 1;
+ dlnew->type= DL_POLY;
+ dlnew->col= dl->col;
+
+ fp= dl->verts+3*(dl->nr-1);
+ dpoly= 3*dl->nr;
+
+ a= dl->parts;
+ while(a--) {
+ VECCOPY(fp1, fp);
+ fp1+= 3;
+ fp+= dpoly;
+ }
+ }
+ }
+ }
+ dl= dl->next;
+ }
+
+ filldisplist(&front, dispbase);
+ filldisplist(&back, dispbase);
+
+ freedisplist(&front);
+ freedisplist(&back);
+
+ filldisplist(dispbase, dispbase);
+
+}
+
+void curve_to_filledpoly(Curve *cu, ListBase *dispbase)
+{
+ DispList *dl;
+ Nurb *nu;
+
+ dl= dispbase->first;
+
+ if(cu->flag & CU_3D) return;
+
+ nu= cu->nurb.first;
+ while(nu) {
+ if(nu->flagu & CU_CYCLIC) break;
+ nu= nu->next;
+ }
+ if(nu==0) return;
+
+ if(dl->type==DL_SURF) bevels_to_filledpoly(cu, dispbase);
+ else {
+ if(cu->flag & CU_FRONT) filldisplist(dispbase, dispbase);
+ }
+}
+
+
+static int dl_onlyzero= 0;
+
+void set_displist_onlyzero(int val)
+{
+ dl_onlyzero= val;
+}
+
+void makeDispList(Object *ob)
+{
+ Mesh *me;
+ Nurb *nu;
+ Curve *cu;
+ BPoint *bp;
+ ListBase dlbev, *dispbase;
+ DispList *dl, *dlb;
+ BevList *bl;
+ BevPoint *bevp;
+ float *data, *fp1, widfac, vec[3];
+ int len, a, b, draw=0;
+
+ if(ob==0) return;
+ if(ob->flag & OB_FROMDUPLI) return;
+ freedisplist(&(ob->disp));
+
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+
+ freedisplist(&(me->disp));
+
+ tex_space_mesh(ob->data);
+
+ object_deform(ob);
+
+ if(ob->effect.first) object_wave(ob);
+
+ if ((me->flag & ME_SUBSURF) && me->subdiv>0) {
+ if (ob==G.obedit)
+ subsurf_make_editmesh(ob);
+ else
+ subsurf_make_mesh(ob, me->subdiv);
+ }
+ }
+ else if(ob->type==OB_MBALL) {
+ ob= find_basis_mball(ob);
+
+ metaball_polygonize(ob);
+ tex_space_mball(ob);
+ }
+ else if(ob->type==OB_SURF) {
+
+ draw= ob->dt;
+ cu= ob->data;
+ dispbase= &(cu->disp);
+ if(dl_onlyzero && dispbase->first) return;
+ freedisplist(dispbase);
+
+ if(ob==G.obedit) nu= editNurb.first;
+ else nu= cu->nurb.first;
+
+ while(nu) {
+ if(nu->hide==0) {
+ if(nu->pntsv==1) {
+ if(draw==0) len= nu->pntsu;
+ else len= nu->pntsu*nu->resolu;
+
+ dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
+ dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
+
+ BLI_addtail(dispbase, dl);
+ dl->parts= 1;
+ dl->nr= len;
+ dl->col= nu->mat_nr;
+
+ data= dl->verts;
+ if(nu->flagu & 1) dl->type= DL_POLY;
+ else dl->type= DL_SEGM;
+
+ if(draw==0) {
+ bp= nu->bp;
+ while(len--) {
+ VECCOPY(data, bp->vec);
+ bp++;
+ data+= 3;
+ }
+ }
+ else makeNurbcurve(nu, data, 3);
+ }
+ else {
+ if(draw==0 && ob==G.obedit) ;
+ else {
+ if(draw==0) len= nu->pntsu*nu->pntsv;
+ else len= nu->resolu*nu->resolv;
+
+ dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
+ dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
+ BLI_addtail(dispbase, dl);
+
+ if(draw==0) {
+ dl->parts= nu->pntsv;
+ dl->nr= nu->pntsu;
+ if(nu->flagu & 1) dl->flag|= 1;
+ if(nu->flagv & 1) dl->flag|= 2;
+ }
+ else {
+ dl->parts= nu->resolu; /* andersom want makeNurbfaces gaat zo */
+ dl->nr= nu->resolv;
+ if(nu->flagv & 1) dl->flag|= 1; /* ook andersom ! */
+ if(nu->flagu & 1) dl->flag|= 2;
+ }
+ dl->col= nu->mat_nr;
+
+ data= dl->verts;
+ dl->type= DL_SURF;
+
+ if(draw==0) {
+ bp= nu->bp;
+ while(len--) {
+ VECCOPY(data, bp->vec);
+ bp++;
+ data+= 3;
+ }
+ }
+ else makeNurbfaces(nu, data);
+ }
+ }
+ }
+ nu= nu->next;
+ }
+
+ tex_space_curve(cu);
+
+ if(ob!=G.obedit) object_deform(ob);
+ }
+ else if ELEM(ob->type, OB_CURVE, OB_FONT) {
+
+ draw= ob->dt;
+ cu= ob->data;
+ dispbase= &(cu->disp);
+ if(dl_onlyzero && dispbase->first) return;
+ freedisplist(dispbase);
+
+ if(cu->path) free_path(cu->path);
+ cu->path= 0;
+
+ BLI_freelistN(&(cu->bev));
+
+ if(ob==G.obedit) {
+ if(ob->type==OB_CURVE) curve_to_displist(&editNurb, dispbase);
+ else curve_to_displist(&cu->nurb, dispbase);
+ if(cu->flag & CU_PATH) makeBevelList(ob);
+ }
+ else if(cu->ext1==0.0 && cu->ext2==0.0 && cu->bevobj==0 && cu->width==1.0) {
+ curve_to_displist(&cu->nurb, dispbase);
+ if(cu->flag & CU_PATH) makeBevelList(ob);
+ }
+ else {
+
+ makeBevelList(ob);
+
+ dlbev.first= dlbev.last= 0;
+ if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj) {
+ if(ob->dt!=0) makebevelcurve(ob, &dlbev);
+ }
+
+ /* met bevellist werken */
+ widfac= cu->width-1.0;
+ bl= cu->bev.first;
+ nu= cu->nurb.first;
+ while(bl) {
+ if(dlbev.first==0) {
+ dl= MEM_callocN(sizeof(DispList), "makeDispListbev");
+ dl->verts= MEM_callocN(3*sizeof(float)*bl->nr, "dlverts");
+ BLI_addtail(dispbase, dl);
+ if(bl->poly!= -1) dl->type= DL_POLY;
+ else dl->type= DL_SEGM;
+ dl->parts= 1;
+ dl->nr= bl->nr;
+ dl->col= nu->mat_nr;
+
+ a= dl->nr;
+ bevp= (BevPoint *)(bl+1);
+ data= dl->verts;
+ while(a--) {
+ data[0]= bevp->x+widfac*bevp->sina;
+ data[1]= bevp->y+widfac*bevp->cosa;
+ data[2]= bevp->z;
+ bevp++;
+ data+=3;
+ }
+ }
+ else {
+ /* voor iedere stuk van de bevel een aparte dispblok maken */
+ dlb= dlbev.first;
+ while(dlb) {
+ dl= MEM_callocN(sizeof(DispList), "makeDispListbev1");
+ dl->verts= MEM_callocN(3*sizeof(float)*dlb->nr*bl->nr, "dlverts");
+ BLI_addtail(dispbase, dl);
+ /* dl->type= dlb->type; */
+
+ dl->type= DL_SURF;
+ dl->flag= 0;
+ if(dlb->type==DL_POLY) dl->flag++;
+ if(bl->poly>=0) dl->flag+=2;
+
+ dl->parts= bl->nr;
+ dl->nr= dlb->nr;
+ dl->col= nu->mat_nr;
+
+ data= dl->verts;
+ bevp= (BevPoint *)(bl+1);
+ a= bl->nr;
+ while(a--) { /* voor ieder punt van poly een bevelstuk maken */
+
+ /* roteer bevelstuk en schrijf in data */
+ fp1= dlb->verts;
+ b= dlb->nr;
+
+ while(b--) {
+ if(cu->flag & CU_3D) {
+
+ vec[0]= fp1[1]+widfac;
+ vec[1]= fp1[2];
+ vec[2]= 0.0;
+
+ Mat3MulVecfl(bevp->mat, vec);
+
+ data[0]= bevp->x+ vec[0];
+ data[1]= bevp->y+ vec[1];
+ data[2]= bevp->z+ vec[2];
+ }
+ else {
+ data[0]= bevp->x+ (fp1[1]+widfac)*bevp->sina;
+ data[1]= bevp->y+ (fp1[1]+widfac)*bevp->cosa;
+ data[2]= bevp->z+ fp1[2];
+ }
+
+ data+=3;
+ fp1+=3;
+ }
+
+ bevp++;
+ }
+
+ dlb= dlb->next;
+ }
+ }
+
+ bl= bl->next;
+ nu= nu->next;
+ }
+
+ if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj) {
+ freedisplist(&dlbev);
+ }
+ }
+
+ if(ob!=G.obedit) object_deform(ob);
+
+ tex_space_curve(cu);
+
+ }
+}
+
+
+/*******************************/
+/***** OUTLINE *****/
+/*******************************/
+
+typedef struct Sample{
+ short x, y;
+} Sample;
+
+typedef struct Segment{
+ /* coordinaten */
+ struct Segment * next, * prev;
+ float co[2];
+} Segment;
+
+
+
+static int dflt_in_out(struct ImBuf * ibuf, int x, int y)
+{
+ unsigned char * rect;
+
+ if (ibuf == 0) return (0);
+ if (x < 0 || y < 0 || x >= ibuf->x || y >= ibuf->y || ibuf->rect == 0) return (-1);
+
+ rect = (unsigned char *) (ibuf->rect + (y * ibuf->x) + x);
+ if (rect[0] > 0x81) return (1);
+ return(0);
+}
+
+
+static Sample * outline(struct ImBuf * ibuf,
+ int (*in_or_out)(struct ImBuf *, int, int))
+{
+ static int dirs[8][2] = {
+ {-1, 0}, {-1, 1}, {0, 1}, {1, 1},
+ {1, 0}, {1, -1}, {0, -1}, {-1, -1}
+ };
+
+ int dir, x, y, in, i;
+ int count, sampcount;
+ int startx = 0, starty = 0;
+ Sample * samp, * oldsamp;
+
+ /* wat erin gaat:
+ * 1 - plaatje waarvan outline berekent moet worden,
+ * 2 - pointer naar functie die bepaalt welke pixel in of uit is
+ */
+
+ if (ibuf == 0) return (0);
+ if (ibuf->rect == 0) return (0);
+
+ if (in_or_out == 0) in_or_out = dflt_in_out;
+ in = in_or_out(ibuf, 0, 0);
+
+ /* zoek naar eerste overgang en ga van daar uit 'zoeken' */
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ if (in_or_out(ibuf, x, y) != in) {
+ /* eerste 'andere' punt gevonden !! */
+
+ if (x != startx) dir = 0;
+ else dir = 6;
+
+ startx = x; starty = y;
+ count = 1;
+ sampcount = 2000;
+ samp = MEM_mallocN(sampcount * sizeof(Sample), "wire_samples");
+
+ do{
+ samp[count].x = x; samp[count].y = y;
+ count++;
+
+ if (count >= sampcount) {
+ oldsamp = samp;
+ samp = MEM_mallocN(2 * sampcount * sizeof(Sample), "wire_samples");
+ memcpy(samp, oldsamp, sampcount * sizeof(Sample));
+ sampcount *= 2;
+ MEM_freeN(oldsamp);
+ }
+
+ i = 0;
+ while(in_or_out(ibuf, x + dirs[dir][0], y + dirs[dir][1]) == in) {
+ dir = (dir + 1) & 0x7;
+ if (i++ == 9) break;
+ }
+
+ if (i >= 8) {
+ /* dit moet een losse punt geweest zijn */
+ break;
+ }
+
+ x += dirs[dir][0];
+ y += dirs[dir][1];
+ dir = (dir - 3) & 0x7;
+ } while(x != startx || y != starty);
+
+ if (i >= 8) {
+ /* losse punten patch */
+ MEM_freeN(samp);
+ } else {
+ count = count - 1;
+ samp[0].x = count >> 16;
+ samp[0].y = count;
+ return(samp);
+ }
+ }
+ }
+ }
+ /* printf("geen overgang \n"); */
+ return(0);
+}
+
+
+
+/*******************************/
+/***** WIREFRAME *****/
+/*******************************/
+
+
+static float DistToLine2D(short *v1, short *v2, short *v3) /* met formule van Hesse :GEEN LIJNSTUK! */
+{
+ float a[2],deler;
+
+ a[0] = v2[1]-v3[1];
+ a[1] = v3[0]-v2[0];
+ deler = sqrt(a[0]*a[0]+a[1]*a[1]);
+ if(deler == 0.0) return 0;
+
+ return fabs((v1[0]-v2[0])*a[0]+(v1[1]-v2[1])*a[1])/deler;
+
+}
+
+static float ComputeMaxShpError(Sample *samp, int first, int last, int *splitPoint)
+ /* samp: Array of digitized points */
+ /* first, last: Indices defining region */
+ /* splitpoint: Point of maximum error */
+{
+ int i;
+ float maxDist; /* Maximum error */
+ float dist; /* Current error */
+
+ *splitPoint = (last - first + 1) / 2;
+ maxDist = 0.0;
+
+ for (i = first + 1; i < last; i++) {
+ dist = DistToLine2D((short *)(samp+i), (short *)(samp+first), (short *)(samp+last));
+
+ if (dist >= maxDist) {
+ maxDist = dist;
+ *splitPoint = i;
+ }
+ }
+
+ return (maxDist);
+}
+
+
+static void FitPoly(Sample *samp, int first, int last, float shperr, ListBase *seglist)
+ /* Samp: Array of digitized points */
+ /* first,last: Indices of first and last pts in region */
+ /* spherr: User-defined error squared */
+{
+ Segment * seg; /* Control points segment*/
+ float maxError; /* Maximum fitting error */
+ int splitPoint; /* Point to split point set at */
+ int nPts; /* Number of points in subset */
+
+ nPts = last - first + 1;
+
+ /* Use heuristic if region only has two points in it */
+
+ seg = MEM_mallocN(sizeof(Segment), "wure_segment");
+
+ seg->co[0] = samp[first].x;
+ seg->co[1] = samp[first].y;
+
+ if (nPts == 2) {
+ BLI_addtail(seglist, seg);
+ return;
+ }
+
+ maxError = ComputeMaxShpError(samp, first, last, &splitPoint);
+ if (maxError < shperr) {
+ BLI_addtail(seglist, seg);
+ return;
+ }
+
+ /* Fitting failed -- split at max error point and fit recursively */
+
+ FitPoly(samp, first, splitPoint, shperr, seglist);
+ FitPoly(samp, splitPoint, last, shperr, seglist);
+
+ MEM_freeN(seg);
+}
+
+
+static void ibuf2wire(ListBase * wireframe, struct ImBuf * ibuf)
+{
+ int count;
+ Sample * samp;
+
+ /* eerst een lijst met samples maken */
+
+ samp = outline(ibuf, 0);
+ if (samp == 0) return;
+
+ count = (samp[0].x << 16) + samp[0].y;
+ if (count) FitPoly(samp, 1, count, 1.0, wireframe); /* was 3.0. Frank */
+
+ MEM_freeN(samp);
+}
+
+
+
+void imagestodisplist(void)
+{
+ Base *base;
+ Object *ob;
+ Material *ma;
+ Tex *tex;
+ Mesh *me;
+ ListBase _wireframe, *wireframe;
+ DispList *dl;
+ Segment *seg;
+ float *data, xfac, yfac, xsi, ysi, vec[3];
+ int tot;
+
+ _wireframe.first= 0;
+ _wireframe.last= 0;
+ wireframe = &_wireframe;
+
+ init_render_textures();
+
+ base= G.scene->base.first;
+ while(base) {
+ if(( (base->flag & SELECT) && (base->lay & G.scene->lay) ) ) {
+ if( base->object->type==OB_MESH) {
+ ob= base->object;
+ me= ob->data;
+
+ ma= give_current_material(ob, 1);
+
+ if(ma && ma->mtex[0] && ma->mtex[0]->tex) {
+ tex= ma->mtex[0]->tex;
+
+ /* dit zorgt voor correct laden van nieuwe imbufs */
+ externtex(ma->mtex[0], vec);
+
+ if(tex->type==TEX_IMAGE && tex->ima && tex->ima->ibuf) {
+
+ ob->dtx |= OB_DRAWIMAGE;
+
+ ibuf2wire(wireframe, tex->ima->ibuf);
+
+ tot= 0;
+ seg = wireframe->first;
+ while (seg) {
+ tot++;
+ seg = seg->next;
+ }
+
+ if(tot) {
+ freedisplist(&(ob->disp));
+
+ dl= MEM_callocN(sizeof(DispList), "makeDispListimage");
+ dl->verts= MEM_callocN(3*sizeof(float)*tot, "dlverts");
+
+ BLI_addtail(&(ob->disp), dl);
+ dl->type= DL_POLY;
+ dl->parts= 1;
+ dl->nr= tot;
+
+ xsi= 0.5*(tex->ima->ibuf->x);
+ ysi= 0.5*(tex->ima->ibuf->y);
+ xfac= me->size[0]/xsi;
+ yfac= me->size[1]/ysi;
+
+ data= dl->verts;
+ seg = wireframe->first;
+ while (seg) {
+ data[0]= xfac*(seg->co[0]-xsi);
+ data[1]= yfac*(seg->co[1]-ysi);
+ data+= 3;
+ seg = seg->next;
+ }
+ BLI_freelistN(wireframe);
+ }
+ }
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ end_render_textures();
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+/* on frame change */
+
+void test_all_displists(void)
+{
+ Base *base;
+ Object *ob;
+ unsigned int lay;
+
+ /* background */
+ lay= G.scene->lay;
+
+ base= G.scene->base.first;
+ while(base) {
+ if(base->lay & lay) {
+ ob= base->object;
+
+
+ if(ob->type==OB_MBALL && ob->ipo) {
+ // find metaball object holding the displist
+ // WARNING: if more metaballs have IPO's the displist
+ // is recalculated to often...
+
+ if(ob->disp.first == NULL) {
+ ob= find_basis_mball(ob);
+ }
+
+ makeDispList(ob);
+ }
+ else if(ob->parent) {
+
+ if (ob->parent->type == OB_LATTICE)
+ makeDispList(ob);
+ else if ((ob->parent->type == OB_IKA) && (ob->partype == PARSKEL))
+ makeDispList(ob);
+#ifdef __NLA
+ else if ((ob->parent->type==OB_ARMATURE) && (ob->partype == PARSKEL))
+ makeDispList(ob);
+
+#endif
+ }
+
+ if ELEM(ob->type, OB_CURVE, OB_SURF) {
+ if(ob!=G.obedit) {
+ if( ((Curve *)(ob->data))->key ) makeDispList(ob);
+ }
+ }
+ else if(ob->type==OB_FONT) {
+ Curve *cu= ob->data;
+ if(cu->textoncurve) {
+ if( ((Curve *)cu->textoncurve->data)->key ) {
+ text_to_curve(ob, 0);
+ makeDispList(ob);
+ }
+ }
+ }
+ else if(ob->type==OB_MESH) {
+ if(ob->effect.first) object_wave(ob);
+ if(ob!=G.obedit) {
+ if( ((Mesh *)(ob->data))->key ) makeDispList(ob);
+ }
+ }
+
+ }
+ if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first;
+ else base= base->next;
+ }
+}
+
+
+void boundbox_displist(Object *ob)
+{
+ BoundBox *bb=0;
+ float min[3], max[3];
+ DispList *dl;
+ float *vert;
+ int a, tot=0;
+
+ INIT_MINMAX(min, max);
+
+ if(ob->type==OB_MESH) {
+ Mesh *me= ob->data;
+
+ dl= find_displist(&ob->disp, DL_VERTS);
+ if(!dl) return;
+
+ if(me->bb==0) me->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
+ bb= me->bb;
+
+ vert= dl->verts;
+ for(a=0; a<dl->nr; a++, vert+=3) {
+ DO_MINMAX(vert, min, max);
+ }
+ }
+ else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ Curve *cu= ob->data;
+
+ if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
+ bb= cu->bb;
+
+ dl= cu->disp.first;
+
+ while (dl) {
+ if(dl->type==DL_INDEX3 || dl->type==DL_INDEX3) tot= dl->nr;
+ else tot= dl->nr*dl->parts;
+
+ vert= dl->verts;
+ for(a=0; a<tot; a++, vert+=3) {
+ DO_MINMAX(vert, min, max);
+ }
+
+ dl= dl->next;
+ }
+ }
+
+ if(bb) {
+ bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= min[0];
+ bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= max[0];
+
+ bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= min[1];
+ bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= max[1];
+
+ bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= min[2];
+ bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= max[2];
+ }
+}
+
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
new file mode 100644
index 00000000000..c39ad72ecdf
--- /dev/null
+++ b/source/blender/blenkernel/intern/effect.c
@@ -0,0 +1,854 @@
+/* effect.c MIX MODEL
+ *
+ * dec 95
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+#include "DNA_listBase.h"
+#include "DNA_effect_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_lattice_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_bad_level_calls.h"
+#include "BKE_global.h"
+#include "BKE_material.h"
+#include "BKE_effect.h"
+#include "BKE_key.h"
+#include "BKE_ipo.h"
+#include "BKE_screen.h"
+#include "BKE_texture.h"
+#include "BKE_blender.h"
+#include "BKE_object.h"
+#include "BKE_displist.h"
+#include "BKE_lattice.h"
+
+
+Effect *add_effect(int type)
+{
+ Effect *eff=0;
+ BuildEff *bld;
+ PartEff *paf;
+ WaveEff *wav;
+ int a;
+
+ switch(type) {
+ case EFF_BUILD:
+ bld= MEM_callocN(sizeof(BuildEff), "neweff");
+ eff= (Effect *)bld;
+
+ bld->sfra= 1.0;
+ bld->len= 100.0;
+ break;
+
+ case EFF_PARTICLE:
+ paf= MEM_callocN(sizeof(PartEff), "neweff");
+ eff= (Effect *)paf;
+
+ paf->sta= 1.0;
+ paf->end= 100.0;
+ paf->lifetime= 50.0;
+ for(a=0; a<PAF_MAXMULT; a++) {
+ paf->life[a]= 50.0;
+ paf->child[a]= 4;
+ paf->mat[a]= 1;
+ }
+
+ paf->totpart= 1000;
+ paf->totkey= 8;
+ paf->staticstep= 5;
+ paf->defvec[2]= 1.0f;
+ paf->nabla= 0.05f;
+
+ break;
+
+ case EFF_WAVE:
+ wav= MEM_callocN(sizeof(WaveEff), "neweff");
+ eff= (Effect *)wav;
+
+ wav->flag |= (WAV_X+WAV_Y+WAV_CYCL);
+
+ wav->height= 0.5f;
+ wav->width= 1.5f;
+ wav->speed= 0.5f;
+ wav->narrow= 1.5f;
+ wav->lifetime= 0.0f;
+ wav->damp= 10.0f;
+
+ break;
+ }
+
+ eff->type= eff->buttype= type;
+ eff->flag |= SELECT;
+
+ return eff;
+}
+
+void free_effect(Effect *eff)
+{
+ PartEff *paf;
+
+ if(eff->type==EFF_PARTICLE) {
+ paf= (PartEff *)eff;
+ if(paf->keys) MEM_freeN(paf->keys);
+ }
+ MEM_freeN(eff);
+}
+
+
+void free_effects(ListBase *lb)
+{
+ Effect *eff;
+
+ eff= lb->first;
+ while(eff) {
+ BLI_remlink(lb, eff);
+ free_effect(eff);
+ eff= lb->first;
+ }
+}
+
+Effect *copy_effect(Effect *eff)
+{
+ Effect *effn;
+
+ effn= MEM_dupallocN(eff);
+ if(effn->type==EFF_PARTICLE) ((PartEff *)effn)->keys= 0;
+
+ return effn;
+}
+
+void copy_act_effect(Object *ob)
+{
+ /* return de aktieve eff gekopieerd */
+ Effect *effn, *eff;
+
+ eff= ob->effect.first;
+ while(eff) {
+ if(eff->flag & SELECT) {
+
+ effn= copy_effect(eff);
+ BLI_addtail(&ob->effect, effn);
+
+ eff->flag &= ~SELECT;
+ return;
+
+ }
+ eff= eff->next;
+ }
+
+ /* als tie hier komt: new effect */
+ eff= add_effect(EFF_BUILD);
+ BLI_addtail(&ob->effect, eff);
+
+}
+
+void copy_effects(ListBase *lbn, ListBase *lb)
+{
+ Effect *eff, *effn;
+
+ lbn->first= lbn->last= 0;
+
+ eff= lb->first;
+ while(eff) {
+ effn= copy_effect(eff);
+ BLI_addtail(lbn, effn);
+
+ eff= eff->next;
+ }
+
+}
+
+void deselectall_eff(Object *ob)
+{
+ Effect *eff= ob->effect.first;
+
+ while(eff) {
+ eff->flag &= ~SELECT;
+ eff= eff->next;
+ }
+}
+
+void set_buildvars(Object *ob, int *start, int *end)
+{
+ BuildEff *bld;
+ float ctime;
+
+ bld= ob->effect.first;
+ while(bld) {
+ if(bld->type==EFF_BUILD) {
+ ctime= bsystem_time(ob, 0, (float)G.scene->r.cfra, bld->sfra-1.0f);
+ if(ctime < 0.0) {
+ *end= *start;
+ }
+ else if(ctime < bld->len) {
+ *end= *start+ (int)((*end - *start)*ctime/bld->len);
+ }
+
+ return;
+ }
+ bld= bld->next;
+ }
+}
+
+/* ***************** PARTICLES ***************** */
+
+Particle *new_particle(PartEff *paf)
+{
+ static Particle *pa;
+ static int cur;
+
+ /* afspraak: als paf->keys==0: alloc */
+ if(paf->keys==0) {
+ pa= paf->keys= MEM_callocN( paf->totkey*paf->totpart*sizeof(Particle), "particlekeys" );
+ cur= 0;
+ }
+ else {
+ if(cur && cur<paf->totpart) pa+=paf->totkey;
+ cur++;
+ }
+ return pa;
+}
+
+PartEff *give_parteff(Object *ob)
+{
+ PartEff *paf;
+
+ paf= ob->effect.first;
+ while(paf) {
+ if(paf->type==EFF_PARTICLE) return paf;
+ paf= paf->next;
+ }
+ return 0;
+}
+
+void where_is_particle(PartEff *paf, Particle *pa, float ctime, float *vec)
+{
+ Particle *p[4];
+ float dt, t[4];
+ int a;
+
+ if(paf->totkey==1) {
+ VECCOPY(vec, pa->co);
+ return;
+ }
+
+ /* eerst op zoek naar de eerste particlekey */
+ a= (int)((paf->totkey-1)*(ctime-pa->time)/pa->lifetime);
+ if(a>=paf->totkey) a= paf->totkey-1;
+
+ pa+= a;
+
+ if(a>0) p[0]= pa-1; else p[0]= pa;
+ p[1]= pa;
+
+ if(a+1<paf->totkey) p[2]= pa+1; else p[2]= pa;
+ if(a+2<paf->totkey) p[3]= pa+2; else p[3]= p[2];
+
+ if(p[1]==p[2]) dt= 0.0;
+ else dt= (ctime-p[1]->time)/(p[2]->time - p[1]->time);
+
+ if(paf->flag & PAF_BSPLINE) set_four_ipo(dt, t, KEY_BSPLINE);
+ else set_four_ipo(dt, t, KEY_CARDINAL);
+
+ vec[0]= t[0]*p[0]->co[0] + t[1]*p[1]->co[0] + t[2]*p[2]->co[0] + t[3]*p[3]->co[0];
+ vec[1]= t[0]*p[0]->co[1] + t[1]*p[1]->co[1] + t[2]*p[2]->co[1] + t[3]*p[3]->co[1];
+ vec[2]= t[0]*p[0]->co[2] + t[1]*p[1]->co[2] + t[2]*p[2]->co[2] + t[3]*p[3]->co[2];
+
+}
+
+
+void particle_tex(MTex *mtex, PartEff *paf, float *co, float *no)
+{
+ extern float Tin, Tr, Tg, Tb;
+ float old;
+
+ externtex(mtex, co);
+
+ if(paf->texmap==PAF_TEXINT) {
+ Tin*= paf->texfac;
+ no[0]+= Tin*paf->defvec[0];
+ no[1]+= Tin*paf->defvec[1];
+ no[2]+= Tin*paf->defvec[2];
+ }
+ else if(paf->texmap==PAF_TEXRGB) {
+ no[0]+= (Tr-0.5f)*paf->texfac;
+ no[1]+= (Tg-0.5f)*paf->texfac;
+ no[2]+= (Tb-0.5f)*paf->texfac;
+ }
+ else { /* PAF_TEXGRAD */
+
+ old= Tin;
+ co[0]+= paf->nabla;
+ externtex(mtex, co);
+ no[0]+= (old-Tin)*paf->texfac;
+
+ co[0]-= paf->nabla;
+ co[1]+= paf->nabla;
+ externtex(mtex, co);
+ no[1]+= (old-Tin)*paf->texfac;
+
+ co[1]-= paf->nabla;
+ co[2]+= paf->nabla;
+ externtex(mtex, co);
+ no[2]+= (old-Tin)*paf->texfac;
+
+ }
+}
+
+void make_particle_keys(int depth, int nr, PartEff *paf, Particle *part, float *force, int deform, MTex *mtex)
+{
+ Particle *pa, *opa = NULL;
+ float damp, deltalife;
+ int b, rt1, rt2;
+
+ damp= 1.0f-paf->damp;
+ pa= part;
+
+ /* startsnelheid: random */
+ if(paf->randfac!=0.0) {
+ pa->no[0]+= (float)(paf->randfac*( BLI_drand() -0.5));
+ pa->no[1]+= (float)(paf->randfac*( BLI_drand() -0.5));
+ pa->no[2]+= (float)(paf->randfac*( BLI_drand() -0.5));
+ }
+
+ /* startsnelheid: texture */
+ if(mtex && paf->texfac!=0.0) {
+ particle_tex(mtex, paf, pa->co, pa->no);
+ }
+
+ /* keys */
+ if(paf->totkey>1) {
+
+ deltalife= pa->lifetime/(paf->totkey-1);
+ opa= pa;
+ pa++;
+
+ b= paf->totkey-1;
+ while(b--) {
+ /* nieuwe tijd */
+ pa->time= opa->time+deltalife;
+
+ /* nieuwe plek */
+ pa->co[0]= opa->co[0] + deltalife*opa->no[0];
+ pa->co[1]= opa->co[1] + deltalife*opa->no[1];
+ pa->co[2]= opa->co[2] + deltalife*opa->no[2];
+
+ /* nieuwe snelheid */
+ pa->no[0]= opa->no[0] + deltalife*force[0];
+ pa->no[1]= opa->no[1] + deltalife*force[1];
+ pa->no[2]= opa->no[2] + deltalife*force[2];
+
+ /* snelheid: texture */
+ if(mtex && paf->texfac!=0.0) {
+ particle_tex(mtex, paf, pa->co, pa->no);
+ }
+ if(damp!=1.0) {
+ pa->no[0]*= damp;
+ pa->no[1]*= damp;
+ pa->no[2]*= damp;
+ }
+
+ opa= pa;
+ pa++;
+ /* opa wordt onderin ook gebruikt */
+ }
+ }
+
+ if(deform) {
+ /* alle keys deformen */
+ pa= part;
+ b= paf->totkey;
+ while(b--) {
+ calc_latt_deform(pa->co);
+ pa++;
+ }
+ }
+
+ /* de grote vermenigvuldiging */
+ if(depth<PAF_MAXMULT && paf->mult[depth]!=0.0) {
+
+ /* uit gemiddeld 'mult' deel van de particles ontstaan 'child' nieuwe */
+ damp = (float)nr;
+ rt1= (int)(damp*paf->mult[depth]);
+ rt2= (int)((damp+1.0)*paf->mult[depth]);
+ if(rt1!=rt2) {
+
+ for(b=0; b<paf->child[depth]; b++) {
+ pa= new_particle(paf);
+ *pa= *opa;
+ pa->lifetime= paf->life[depth];
+ if(paf->randlife!=0.0) {
+ pa->lifetime*= 1.0f+ (float)(paf->randlife*( BLI_drand() - 0.5));
+ }
+ pa->mat_nr= paf->mat[depth];
+
+ make_particle_keys(depth+1, b, paf, pa, force, deform, mtex);
+ }
+ }
+ }
+}
+
+void init_mv_jit(float *jit, int num)
+{
+ float *jit2, x, rad1, rad2, rad3;
+ int i;
+
+ if(num==0) return;
+
+ rad1= (float)(1.0/sqrt((float)num));
+ rad2= (float)(1.0/((float)num));
+ rad3= (float)sqrt((float)num)/((float)num);
+
+ BLI_srand(31415926 + num);
+ x= 0;
+ for(i=0; i<2*num; i+=2) {
+
+ jit[i]= x+ (float)(rad1*(0.5-BLI_drand()));
+ jit[i+1]= ((float)i/2)/num +(float)(rad1*(0.5-BLI_drand()));
+
+ jit[i]-= (float)floor(jit[i]);
+ jit[i+1]-= (float)floor(jit[i+1]);
+
+ x+= rad3;
+ x -= (float)floor(x);
+ }
+
+ jit2= MEM_mallocN(12 + 2*sizeof(float)*num, "initjit");
+
+ for (i=0 ; i<4 ; i++) {
+ RE_jitterate1(jit, jit2, num, rad1);
+ RE_jitterate1(jit, jit2, num, rad1);
+ RE_jitterate2(jit, jit2, num, rad2);
+ }
+ MEM_freeN(jit2);
+}
+
+
+void give_mesh_mvert(Mesh *me, int nr, float *co, short *no)
+{
+ static float *jit=0;
+ static int jitlevel=1;
+ MVert *mvert;
+ MFace *mface;
+ float u, v, *v1, *v2, *v3, *v4;
+ int curface, curjit;
+ short *n1, *n2, *n3, *n4;
+
+ /* signal */
+ if(me==0) {
+ if(jit) MEM_freeN(jit);
+ jit= 0;
+ return;
+ }
+
+ if(me->totface==0 || nr<me->totvert) {
+ mvert= me->mvert + (nr % me->totvert);
+ VECCOPY(co, mvert->co);
+ VECCOPY(no, mvert->no);
+ }
+ else {
+
+ nr-= me->totvert;
+
+ if(jit==0) {
+ jitlevel= nr/me->totface;
+ if(jitlevel==0) jitlevel= 1;
+ if(jitlevel>100) jitlevel= 100;
+
+ jit= MEM_callocN(2+ jitlevel*2*sizeof(float), "jit");
+ init_mv_jit(jit, jitlevel);
+
+ }
+
+ curjit= nr/me->totface;
+ curjit= curjit % jitlevel;
+
+ curface= nr % me->totface;
+
+ mface= me->mface;
+ mface+= curface;
+
+ v1= (me->mvert+(mface->v1))->co;
+ v2= (me->mvert+(mface->v2))->co;
+ n1= (me->mvert+(mface->v1))->no;
+ n2= (me->mvert+(mface->v2))->no;
+ if(mface->v3==0) {
+ v3= (me->mvert+(mface->v2))->co;
+ v4= (me->mvert+(mface->v1))->co;
+ n3= (me->mvert+(mface->v2))->no;
+ n4= (me->mvert+(mface->v1))->no;
+ }
+ else if(mface->v4==0) {
+ v3= (me->mvert+(mface->v3))->co;
+ v4= (me->mvert+(mface->v1))->co;
+ n3= (me->mvert+(mface->v3))->no;
+ n4= (me->mvert+(mface->v1))->no;
+ }
+ else {
+ v3= (me->mvert+(mface->v3))->co;
+ v4= (me->mvert+(mface->v4))->co;
+ n3= (me->mvert+(mface->v3))->no;
+ n4= (me->mvert+(mface->v4))->no;
+ }
+
+ u= jit[2*curjit];
+ v= jit[2*curjit+1];
+
+ co[0]= (float)((1.0-u)*(1.0-v)*v1[0] + (1.0-u)*(v)*v2[0] + (u)*(v)*v3[0] + (u)*(1.0-v)*v4[0]);
+ co[1]= (float)((1.0-u)*(1.0-v)*v1[1] + (1.0-u)*(v)*v2[1] + (u)*(v)*v3[1] + (u)*(1.0-v)*v4[1]);
+ co[2]= (float)((1.0-u)*(1.0-v)*v1[2] + (1.0-u)*(v)*v2[2] + (u)*(v)*v3[2] + (u)*(1.0-v)*v4[2]);
+
+ no[0]= (short)((1.0-u)*(1.0-v)*n1[0] + (1.0-u)*(v)*n2[0] + (u)*(v)*n3[0] + (u)*(1.0-v)*n4[0]);
+ no[1]= (short)((1.0-u)*(1.0-v)*n1[1] + (1.0-u)*(v)*n2[1] + (u)*(v)*n3[1] + (u)*(1.0-v)*n4[1]);
+ no[2]= (short)((1.0-u)*(1.0-v)*n1[2] + (1.0-u)*(v)*n2[2] + (u)*(v)*n3[2] + (u)*(1.0-v)*n4[2]);
+
+ }
+}
+
+
+void build_particle_system(Object *ob)
+{
+ Object *par;
+ PartEff *paf;
+ Particle *pa;
+ Mesh *me;
+ MVert *mvert;
+ MTex *mtexmove=0;
+ Material *ma;
+ float framelenont, ftime, dtime, force[3], imat[3][3], vec[3];
+ float fac, prevobmat[4][4], sfraont, co[3];
+ int deform=0, a, cur, cfraont, cfralast, totpart;
+ short no[3];
+
+ if(ob->type!=OB_MESH) return;
+ me= ob->data;
+ if(me->totvert==0) return;
+
+ ma= give_current_material(ob, 1);
+ if(ma) {
+ mtexmove= ma->mtex[7];
+ }
+
+ paf= give_parteff(ob);
+ if(paf==0) return;
+
+ waitcursor(1);
+
+ disable_speed_curve(1);
+
+ /* alle particles genereren */
+ if(paf->keys) MEM_freeN(paf->keys);
+ paf->keys= 0;
+ new_particle(paf);
+
+ cfraont= G.scene->r.cfra;
+ cfralast= -1000;
+ framelenont= G.scene->r.framelen;
+ G.scene->r.framelen= 1.0;
+ sfraont= ob->sf;
+ ob->sf= 0.0;
+
+ /* mult generaties? */
+ totpart= paf->totpart;
+ for(a=0; a<PAF_MAXMULT; a++) {
+ if(paf->mult[a]!=0.0) {
+ /* interessante formule! opdezewijze is na 'x' generaties het totale aantal paf->totpart */
+ totpart= (int)(totpart / (1.0+paf->mult[a]*paf->child[a]));
+ }
+ else break;
+ }
+
+ ftime= paf->sta;
+ dtime= (paf->end - paf->sta)/totpart;
+
+ /* hele hiera onthouden */
+ par= ob;
+ while(par) {
+ pushdata(par, sizeof(Object));
+ par= par->parent;
+ }
+
+ /* alles op eerste frame zetten */
+ G.scene->r.cfra= cfralast= (int)floor(ftime);
+ par= ob;
+ while(par) {
+ /* do_ob_ipo(par); */
+ do_ob_key(par);
+ par= par->parent;
+ }
+ do_mat_ipo(ma);
+
+ if((paf->flag & PAF_STATIC)==0) {
+ where_is_object(ob);
+ Mat4CpyMat4(prevobmat, ob->obmat);
+ Mat4Invert(ob->imat, ob->obmat);
+ Mat3CpyMat4(imat, ob->imat);
+ }
+ else {
+ Mat4One(prevobmat);
+ Mat3One(imat);
+ }
+
+ BLI_srand(paf->seed);
+
+ /* gaat anders veuls te hard */
+ force[0]= paf->force[0]*0.05f;
+ force[1]= paf->force[1]*0.05f;
+ force[2]= paf->force[2]*0.05f;
+
+ deform= (ob->parent && ob->parent->type==OB_LATTICE);
+ if(deform) init_latt_deform(ob->parent, 0);
+
+ /* init */
+ give_mesh_mvert(me, totpart, co, no);
+
+ for(a=0; a<totpart; a++, ftime+=dtime) {
+
+ pa= new_particle(paf);
+ pa->time= ftime;
+
+ /* ob op juiste tijd zetten */
+
+ if((paf->flag & PAF_STATIC)==0) {
+
+ cur= (int)floor(ftime) + 1 ; /* + 1 heeft een reden: (obmat/prevobmat) anders beginnen b.v. komeetstaartjes te laat */
+ if(cfralast != cur) {
+ G.scene->r.cfra= cfralast= cur;
+
+ /* later bijgevoegd: blur? */
+ bsystem_time(ob, ob->parent, (float)G.scene->r.cfra, 0.0);
+
+ par= ob;
+ while(par) {
+ /* do_ob_ipo(par); */
+ par->ctime= -1234567.0;
+ do_ob_key(par);
+ par= par->parent;
+ }
+ do_mat_ipo(ma);
+ Mat4CpyMat4(prevobmat, ob->obmat);
+ where_is_object(ob);
+ Mat4Invert(ob->imat, ob->obmat);
+ Mat3CpyMat4(imat, ob->imat);
+ }
+ }
+ /* coordinaat ophalen */
+ if(paf->flag & PAF_FACE) give_mesh_mvert(me, a, co, no);
+ else {
+ mvert= me->mvert + (a % me->totvert);
+ VECCOPY(co, mvert->co);
+ VECCOPY(no, mvert->no);
+ }
+
+ VECCOPY(pa->co, co);
+
+ if(paf->flag & PAF_STATIC);
+ else {
+ Mat4MulVecfl(ob->obmat, pa->co);
+
+ VECCOPY(vec, co);
+ Mat4MulVecfl(prevobmat, vec);
+
+ /* eerst even startsnelheid: object */
+ VecSubf(pa->no, pa->co, vec);
+ VecMulf(pa->no, paf->obfac);
+
+ /* nu juiste interframe co berekenen */
+ fac= (ftime- (float)floor(ftime));
+ pa->co[0]= fac*pa->co[0] + (1.0f-fac)*vec[0];
+ pa->co[1]= fac*pa->co[1] + (1.0f-fac)*vec[1];
+ pa->co[2]= fac*pa->co[2] + (1.0f-fac)*vec[2];
+ }
+
+ /* startsnelheid: normaal */
+ if(paf->normfac!=0.0) {
+ /* sp= mvert->no; */
+ /* transpose ! */
+ vec[0]= imat[0][0]*no[0] + imat[0][1]*no[1] + imat[0][2]*no[2];
+ vec[1]= imat[1][0]*no[0] + imat[1][1]*no[1] + imat[1][2]*no[2];
+ vec[2]= imat[2][0]*no[0] + imat[2][1]*no[1] + imat[2][2]*no[2];
+
+ Normalise(vec);
+ VecMulf(vec, paf->normfac);
+ VecAddf(pa->no, pa->no, vec);
+ }
+ pa->lifetime= paf->lifetime;
+ if(paf->randlife!=0.0) {
+ pa->lifetime*= 1.0f+ (float)(paf->randlife*( BLI_drand() - 0.5));
+ }
+ pa->mat_nr= 1;
+
+ make_particle_keys(0, a, paf, pa, force, deform, mtexmove);
+ }
+
+ if(deform) end_latt_deform();
+
+ /* restore */
+ G.scene->r.cfra= cfraont;
+ G.scene->r.framelen= framelenont;
+ give_mesh_mvert(0, 0, 0, 0);
+
+
+ /* hele hiera terug */
+ par= ob;
+ while(par) {
+ popfirst(par);
+ /* geen ob->ipo doen: insertkey behouden */
+ do_ob_key(par);
+ par= par->parent;
+ }
+
+ /* restore: NA popfirst */
+ ob->sf= sfraont;
+
+ disable_speed_curve(0);
+
+ waitcursor(0);
+
+}
+
+/* ************* WAVE **************** */
+
+void calc_wave_deform(WaveEff *wav, float ctime, float *co)
+{
+ /* co is in lokale coords */
+ float lifefac, x, y, amplit;
+
+ /* mag eigenlijk niet voorkomen */
+ if((wav->flag & (WAV_X+WAV_Y))==0) return;
+
+ lifefac= wav->height;
+
+ if( wav->lifetime!=0.0) {
+ x= ctime - wav->timeoffs;
+ if(x>wav->lifetime) {
+
+ lifefac= x-wav->lifetime;
+
+ if(lifefac > wav->damp) lifefac= 0.0;
+ else lifefac= (float)(wav->height*(1.0 - sqrt(lifefac/wav->damp)));
+ }
+ }
+ if(lifefac==0.0) return;
+
+ x= co[0]-wav->startx;
+ y= co[1]-wav->starty;
+
+ if(wav->flag & WAV_X) {
+ if(wav->flag & WAV_Y) amplit= (float)sqrt( (x*x + y*y));
+ else amplit= x;
+ }
+ else amplit= y;
+
+ /* zo maaktie mooie cirkels */
+ amplit-= (ctime-wav->timeoffs)*wav->speed;
+
+ if(wav->flag & WAV_CYCL) {
+ amplit = (float)fmod(amplit-wav->width, 2.0*wav->width) + wav->width;
+ }
+
+ /* GAUSSIAN */
+
+ if(amplit> -wav->width && amplit<wav->width) {
+
+ amplit = amplit*wav->narrow;
+ amplit= (float)(1.0/exp(amplit*amplit) - wav->minfac);
+
+ co[2]+= lifefac*amplit;
+ }
+}
+
+void object_wave(Object *ob)
+{
+ WaveEff *wav;
+ DispList *dl;
+ Mesh *me;
+ MVert *mvert;
+ float *fp, ctime;
+ int a, first;
+
+ /* is er een mave */
+ wav= ob->effect.first;
+ while(wav) {
+ if(wav->type==EFF_WAVE) break;
+ wav= wav->next;
+ }
+ if(wav==0) return;
+
+ if(ob->type==OB_MESH) {
+
+ ctime= bsystem_time(ob, 0, (float)G.scene->r.cfra, 0.0);
+ first= 1;
+
+ me= ob->data;
+ dl= find_displist_create(&ob->disp, DL_VERTS);
+
+ if(dl->verts) MEM_freeN(dl->verts);
+ dl->nr= me->totvert;
+ dl->verts= MEM_mallocN(3*4*me->totvert, "wave");
+
+ wav= ob->effect.first;
+ while(wav) {
+ if(wav->type==EFF_WAVE) {
+
+ /* voorberekenen */
+ wav->minfac= (float)(1.0/exp(wav->width*wav->narrow*wav->width*wav->narrow));
+ if(wav->damp==0) wav->damp= 10.0f;
+
+ mvert= me->mvert;
+ fp= dl->verts;
+
+ for(a=0; a<me->totvert; a++, mvert++, fp+=3) {
+ if(first) VECCOPY(fp, mvert->co);
+ calc_wave_deform(wav, ctime, fp);
+ }
+ first= 0;
+ }
+ wav= wav->next;
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c
new file mode 100644
index 00000000000..104b1b24efe
--- /dev/null
+++ b/source/blender/blenkernel/intern/exotic.c
@@ -0,0 +1,4081 @@
+/* exotic.c mei 95 MIXED MODEL
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * eigen videoscape formaat:
+ *
+ *
+ * lamp:
+ * 3DG2
+ aantal_lampen
+
+ type
+ spsi spbl
+ r, g, b, energy
+ locx, locy, locz
+ vecx, vecy, vecz
+
+
+ curve / nurbs:
+ 3DG3
+ 5 of 11 (curve of surf)
+ aantal_nurbs
+ extr1 extr2
+
+ mat[0][0] mat[0][1] mat[0][2] mat[0][3]
+ mat[1][0] mat[1][1] mat[1][2] mat[1][3]
+ ...
+
+ type
+ pntsu, pntsv
+ resolu, resolv
+ orderu, orderv
+ flagu, flagv
+
+ (als type==nurb) x y z w
+ x y z w
+ ...
+ (als type==bez) xyz xyz xyz h1 h2 h3
+ xyz xyz xyz h1 h2 h3
+ ...
+ *
+ *
+ */
+
+
+#include <ctype.h> /* isdigit, isspace */
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include "BLI_winstuff.h"
+#include <io.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_image_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_library.h"
+#include "BKE_global.h"
+#include "BKE_object.h"
+#include "BKE_material.h"
+#include "BKE_exotic.h"
+/* #include "BKE_error.h" */
+#include "BKE_screen.h"
+#include "BKE_displist.h"
+#include "BKE_curve.h"
+
+#include "BPY_extern.h"
+
+/***/
+
+static int is_dxf(char *str);
+static void dxf_read(char *filename);
+
+/***/
+
+static void read_videoscape_mesh(char *str)
+{
+ Object *ob;
+ Mesh *me;
+ MVert *mvert;
+ MFace *mface;
+ Material *ma;
+ FILE *fp;
+ float *vertdata, *vd, min[3], max[3], cent[3], ftemp;
+ unsigned int color[32], col;
+ int totcol, a, b, verts, tottria=0, totquad=0, totedge=0, poly, nr0, nr, first;
+ short end;
+ char s[50];
+
+ fp= fopen(str, "rb");
+ if(fp==NULL) {
+ error("Can't read file");
+ return;
+ }
+
+ fscanf(fp, "%40s", s);
+
+ fscanf(fp, "%d\n", &verts);
+ if(verts<=0) {
+ fclose(fp);
+ error("Read error");
+ return;
+ }
+
+ if(verts>65000) {
+ error("too many vertices");
+ fclose(fp);
+ return;
+ }
+
+ INIT_MINMAX(min, max);
+ vd= vertdata= MEM_mallocN(sizeof(float)*3*verts, "videoscapelezer");
+
+ for(a=0; a<verts; a++) {
+ fscanf(fp, "%f %f %f", vd, vd+1, vd+2);
+ DO_MINMAX(vd, min, max);
+ vd+=3;
+ }
+
+ /* de vlakken en kleuren tellen */
+ for(a=0; a<32; a++) color[a]= 0;
+ totcol= 0;
+ end= 1;
+ while(end>0) {
+ end= fscanf(fp,"%d", &poly);
+ if(end<=0) break;
+
+ if(poly==3) tottria++;
+ else if(poly==4) totquad++;
+ else totedge+= poly;
+
+ for(a=0;a<poly;a++) {
+ end= fscanf(fp,"%d", &nr);
+ if(end<=0) break;
+ }
+ if(end<=0) break;
+
+ end= fscanf(fp,"%i\n", &col);
+ col &= 0xF0F0F0;
+ for(a=0; a<totcol; a++) {
+ if(color[a]==col) break;
+ }
+ if(a>=totcol && totcol<32) {
+ color[totcol]= col;
+ totcol++;
+ }
+ }
+
+ if(totedge+tottria+totquad>65000) {
+ printf(" var1: %d, var2: %d, var3: %d \n", totedge, tottria, totquad);
+ error("too many faces");
+ MEM_freeN(vertdata);
+ fclose(fp);
+ return;
+ }
+
+ /* nieuw object */
+ ob= add_object(OB_MESH);
+ me= ob->data;
+ me->totvert= verts;
+ me->totface= totedge+tottria+totquad;
+
+ me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+ if(me->totface) me->mface= MEM_callocN(me->totface*sizeof(MFace), "mface");
+
+ /* kleuren */
+ if(totcol) {
+ ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat");
+ me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat");
+ me->totcol= totcol;
+ ob->totcol= (unsigned char) me->totcol;
+ ob->actcol= 1;
+ }
+
+ /* materialen */
+ for(a=0; a<totcol; a++) {
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->mtex[0]==0) {
+ col= rgb_to_cpack(ma->r, ma->g, ma->b);
+ if(color[a]==col) {
+ me->mat[a]= ma;
+ ma->id.us++;
+ break;
+ }
+ }
+ ma= ma->id.next;
+ }
+ if(ma==0) {
+ ma= add_material("ext");
+ me->mat[a]= ma;
+ cpack_to_rgb(color[a], cent, cent+1, cent+2);
+ ma->r= cent[0];
+ ma->g= cent[1];
+ ma->b= cent[2];
+ automatname(ma);
+ }
+ }
+
+ /* verts */
+
+ cent[0]= (min[0]+max[0])/2.0f;
+ cent[1]= (min[1]+max[1])/2.0f;
+ cent[2]= (min[2]+max[2])/2.0f;
+ VECCOPY(ob->loc, cent);
+
+ a= me->totvert;
+ vd= vertdata;
+ mvert= me->mvert;
+ while(a--) {
+ VecSubf(mvert->co, vd, cent);
+ mvert++;
+ vd+= 3;
+ }
+
+ /* faces */
+ if(me->totface) {
+ rewind(fp);
+
+ fscanf(fp, "%40s", s);
+ fscanf(fp, "%d\n", &verts);
+ /* fake read */
+ for(a=0;a<verts;a++) {
+ fscanf(fp, "%f %f %f", &ftemp, &ftemp, &ftemp);
+ }
+
+ a= me->totface;
+ mface= me->mface;
+ while(a--) {
+ end= fscanf(fp,"%d", &poly);
+ if(end<=0) break;
+
+ if(poly==3 || poly==4) {
+ fscanf(fp,"%d", &nr);
+ mface->v1= MIN2(nr, me->totvert-1);
+ fscanf(fp,"%d", &nr);
+ mface->v2= MIN2(nr, me->totvert-1);
+ fscanf(fp,"%d", &nr);
+ mface->v3= MIN2(nr, me->totvert-1);
+ if(poly==4) {
+ if( fscanf(fp,"%d", &nr) <=0 ) break;
+ mface->v4= MIN2(nr, me->totvert-1);
+ }
+ mface->edcode= 3;
+
+ test_index_mface(mface, poly);
+
+ mface++;
+ }
+ else {
+ if( fscanf(fp,"%d", &nr0) <=0) break;
+ first= nr0;
+ for(b=1; b<poly; b++) {
+ end= fscanf(fp,"%d", &nr);
+ if(end<=0) break;
+ nr= MIN2(nr, me->totvert-1);
+ mface->v1= nr;
+ mface->v2= nr0;
+ nr0= nr;
+ mface++;
+ a--;
+ }
+ mface->v1= first;
+ mface->v2= nr;
+ mface->edcode= 1;
+ mface++;
+ if(end<=0) break;
+ }
+ end= fscanf(fp,"%i", &col);
+ col &= 0xF0F0F0;
+ if(end<=0) break;
+
+ for(b=0; b<totcol; b++) {
+ if(color[b]==col) {
+ (mface-1)->mat_nr= b;
+ break;
+ }
+ }
+ }
+ }
+
+ fclose(fp);
+ MEM_freeN(vertdata);
+
+ G.obedit= ob;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+ G.obedit= 0;
+ tex_space_mesh(me);
+ waitcursor(1);
+}
+
+static void read_radiogour(char *str)
+{
+ Object *ob;
+ Mesh *me;
+ MVert *mvert;
+ MFace *mface;
+ FILE *fp;
+ float *vertdata, *vd, min[3], max[3], cent[3], ftemp;
+ unsigned int *colv, *colf, *colvertdata;
+ int itemp, a, b, verts, tottria=0, totquad=0, totedge=0, poly, nr0, nr, first;
+ short end;
+ char s[50];
+
+ fp= fopen(str, "rb");
+ if(fp==NULL) {
+ error("Can't read file");
+ return;
+ }
+
+ fscanf(fp, "%40s", s);
+
+ fscanf(fp, "%d\n", &verts);
+ if(verts<=0) {
+ fclose(fp);
+ error("Read error");
+ return;
+ }
+
+ if(verts>65000) {
+ error("too many vertices");
+ fclose(fp);
+ return;
+ }
+
+ INIT_MINMAX(min, max);
+ vd= vertdata= MEM_mallocN(sizeof(float)*3*verts, "videoscapelezer");
+ colv= colvertdata= MEM_mallocN(verts*sizeof(float), "coldata");
+
+ for(a=0; a<verts; a++) {
+ fscanf(fp, "%f %f %f %i", vd, vd+1, vd+2, colv);
+ DO_MINMAX(vd, min, max);
+ vd+=3;
+ colv++;
+ }
+
+ /* de vlakken tellen */
+ end= 1;
+ while(end>0) {
+ end= fscanf(fp,"%d", &poly);
+ if(end<=0) break;
+
+ if(poly==3) tottria++;
+ else if(poly==4) totquad++;
+ else totedge+= poly;
+
+ for(a=0;a<poly;a++) {
+ end= fscanf(fp,"%d", &nr);
+ if(end<=0) break;
+ }
+ if(end<=0) break;
+
+ }
+
+ if(totedge+tottria+totquad>65000) {
+ printf(" var1: %d, var2: %d, var3: %d \n", totedge, tottria, totquad);
+ error("too many faces");
+ MEM_freeN(vertdata);
+ MEM_freeN(colvertdata);
+ fclose(fp);
+ return;
+ }
+
+ /* nieuw object */
+ ob= add_object(OB_MESH);
+ me= ob->data;
+ me->totvert= verts;
+ me->totface= totedge+tottria+totquad;
+ me->flag= 0;
+ me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+ if(me->totface) me->mface= MEM_callocN(me->totface*sizeof(MFace), "mface");
+
+ /* verts */
+
+ cent[0]= (min[0]+max[0])/2.0f;
+ cent[1]= (min[1]+max[1])/2.0f;
+ cent[2]= (min[2]+max[2])/2.0f;
+ VECCOPY(ob->loc, cent);
+
+ a= me->totvert;
+ vd= vertdata;
+ mvert= me->mvert;
+ while(a--) {
+ VecSubf(mvert->co, vd, cent);
+ mvert++;
+ vd+= 3;
+ }
+
+ /* faces */
+ if(me->totface) {
+ rewind(fp);
+
+ fscanf(fp, "%40s", s);
+ fscanf(fp, "%d\n", &verts);
+ for(a=0;a<verts;a++) {
+ fscanf(fp, "%f %f %f %i", &ftemp, &ftemp, &ftemp, &itemp);
+ }
+
+ a= me->totface;
+ mface= me->mface;
+ while(a--) {
+ end= fscanf(fp,"%d", &poly);
+ if(end<=0) break;
+
+ if(poly==3 || poly==4) {
+ fscanf(fp,"%d", &nr);
+ mface->v1= MIN2(nr, me->totvert-1);
+ fscanf(fp,"%d", &nr);
+ mface->v2= MIN2(nr, me->totvert-1);
+ fscanf(fp,"%d", &nr);
+ mface->v3= MIN2(nr, me->totvert-1);
+ if(poly==4) {
+ if( fscanf(fp,"%d", &nr) <=0 ) break;
+ mface->v4= MIN2(nr, me->totvert-1);
+ }
+ mface->edcode= 3;
+
+ test_index_mface(mface, poly);
+
+ mface++;
+ }
+ else {
+ if( fscanf(fp,"%d", &nr0) <=0) break;
+ first= nr0;
+ for(b=1; b<poly; b++) {
+ end= fscanf(fp,"%d", &nr);
+ if(end<=0) break;
+ nr= MIN2(nr, me->totvert-1);
+ mface->v1= nr;
+ mface->v2= nr0;
+ nr0= nr;
+ mface++;
+ a--;
+ }
+ mface->v1= first;
+ mface->v2= nr;
+ mface->edcode= 1;
+ mface->flag= ME_SMOOTH;
+
+ mface++;
+ if(end<=0) break;
+ }
+ }
+
+ /* mcol is per vlak 4 kleuren */
+ me->mcol= MEM_mallocN(4*sizeof(int)*me->totface, "mcol");
+ colf= (unsigned int *)me->mcol;
+
+ a= me->totface;
+ mface= me->mface;
+ while(a--) {
+
+ colf[0]= colvertdata[mface->v1];
+ colf[1]= colvertdata[mface->v2];
+ colf[2]= colvertdata[mface->v3];
+ colf[3]= colvertdata[mface->v4];
+
+ colf+= 4;
+ mface++;
+ }
+
+ MEM_freeN(colvertdata);
+ }
+
+ fclose(fp);
+ MEM_freeN(vertdata);
+
+ G.obedit= ob;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+
+ G.obedit= 0;
+ tex_space_mesh(me);
+
+ waitcursor(1);
+}
+
+
+static void read_videoscape_lamp(char *str)
+{
+ Object *ob;
+ Lamp *la;
+ FILE *fp;
+ float vec[3], *q1;
+ int tot, val;
+ char s[50];
+
+ fp= fopen(str, "rb");
+ if(fp==NULL) {
+ error("Can't read file");
+ return;
+ }
+
+ fscanf(fp, "%40s", s);
+ fscanf(fp, "%d\n", &tot);
+
+ while(tot--) {
+ ob= add_object(OB_LAMP);
+ la= ob->data;
+
+ fscanf(fp, "%d\n", &val);
+ la->type= val;
+ if(la->type==1) la->type= LA_SPOT;
+ else if(la->type==2) la->type= LA_SUN;
+
+ fscanf(fp, "%f %f\n", &la->spotsize, &la->spotblend);
+
+ fscanf(fp, "%f %f %f %f\n", &la->r, &la->g, &la->b, &la->energy);
+
+ fscanf(fp, "%f %f %f\n", ob->loc, ob->loc+1, ob->loc+2);
+ val= fscanf(fp, "%f %f %f\n", vec, vec+1, vec+2);
+ q1= vectoquat(vec, 5, 2);
+ QuatToEul(q1, ob->rot);
+
+ if(val<=0) break;
+
+ }
+ fclose(fp);
+}
+
+static void read_videoscape_nurbs(char *str)
+{
+ Object *ob;
+ Curve *cu;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ FILE *fp;
+ float tmat[4][4], omat[3][3], imat[3][3], mat[3][3];
+ int a, tot, type, val;
+ char s[50];
+
+ fp= fopen(str, "rb");
+ if(fp==NULL) {
+ error("Can't read file");
+ return;
+ }
+
+ fscanf(fp, "%40s", s);
+ fscanf(fp, "%d\n", &type);
+
+ if(type==5) ob= add_object(OB_SURF);
+ else ob= add_object(OB_CURVE);
+ cu= ob->data;
+
+ fscanf(fp, "%d\n", &tot);
+ fscanf(fp, "%d %d\n", &type, &val);
+
+ cu->ext1= 0.002f*type;
+ cu->ext2= 0.002f*val;
+
+ for(a=0; a<4; a++) fscanf(fp, "%e %e %e %e\n", tmat[a], tmat[a]+1, tmat[a]+2, tmat[a]+3);
+
+ VECCOPY(ob->loc, tmat[3]);
+
+ Mat3CpyMat4(omat, tmat);
+ Mat3ToEul(omat, ob->rot);
+ EulToMat3(ob->rot, mat);
+ Mat3Inv(imat, mat);
+ Mat3MulMat3(tmat, imat, omat);
+
+ while(tot--) {
+ nu= (Nurb*)MEM_callocN(sizeof(Nurb),"nu from exotic");
+ BLI_addtail(&cu->nurb, nu);
+
+ fscanf(fp, "%d\n", &type);
+ nu->type= type;
+
+ fscanf(fp, "%d %d\n", &type, &val);
+ nu->pntsu= type; nu->pntsv= val;
+ fscanf(fp, "%d %d\n", &type, &val);
+ nu->resolu= type; nu->resolv= val;
+ fscanf(fp, "%d %d\n", &type, &val);
+ nu->orderu= type; nu->orderv= val;
+ fscanf(fp, "%d %d\n", &type, &val);
+ nu->flagu= type; nu->flagv= val;
+
+ if( (nu->type & 7)==CU_BEZIER) {
+ a= nu->pntsu;
+ nu->bezt= bezt= MEM_callocN(a*sizeof(BezTriple), "bezt from exotic");
+ while(a--) {
+ fscanf(fp, "%f %f %f ", bezt->vec[0], bezt->vec[0]+1, bezt->vec[0]+2);
+ Mat4MulVecfl(tmat, bezt->vec[0]);
+ fscanf(fp, "%f %f %f ", bezt->vec[1], bezt->vec[1]+1, bezt->vec[1]+2);
+ Mat4MulVecfl(tmat, bezt->vec[1]);
+ fscanf(fp, "%f %f %f ", bezt->vec[2], bezt->vec[2]+1, bezt->vec[2]+2);
+ Mat4MulVecfl(tmat, bezt->vec[2]);
+ fscanf(fp, "%d %d\n", &type, &val);
+ bezt->h1= type;
+ bezt->h2= val;
+ bezt++;
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ if(a) {
+ nu->bp= bp= MEM_callocN(a*sizeof(BPoint), "bp from exotic");
+ while(a--) {
+ fscanf(fp, "%f %f %f %f\n", bp->vec, bp->vec+1, bp->vec+2, bp->vec+3);
+ Mat4MulVecfl(tmat, bp->vec);
+ bp++;
+ }
+
+ val= KNOTSU(nu);
+ nu->knotsu= MEM_mallocN(sizeof(float)*val, "knots");
+ for(a=0; a<val; a++) fscanf(fp, "%f\n", nu->knotsu+a);
+
+ if(nu->pntsv>1) {
+ val= KNOTSV(nu);
+ nu->knotsv= MEM_mallocN(sizeof(float)*val, "knots");
+ for(a=0; a<val; a++) fscanf(fp, "%f\n", nu->knotsv+a);
+ }
+ }
+ else {
+ BLI_remlink(&cu->nurb, nu);
+ MEM_freeN(nu);
+ }
+ }
+ }
+ fclose(fp);
+ makeDispList(ob);
+}
+
+static void read_videoscape(char *str)
+{
+ int file, type;
+ unsigned short val, numlen;
+ char name[FILE_MAXDIR+FILE_MAXFILE], head[FILE_MAXFILE], tail[FILE_MAXFILE];
+
+ strcpy(name, str);
+
+ while( TRUE ) {
+ file= open(name, O_BINARY|O_RDONLY);
+ if(file<=0) break;
+ else {
+ read(file, &type, 4);
+ close(file);
+
+ if(type==DDG1) read_videoscape_mesh(name);
+ else if(type==DDG2) read_videoscape_lamp(name);
+ else if(type==DDG3) read_videoscape_nurbs(name);
+ }
+
+ val = BLI_stringdec(name, head, tail, &numlen);
+ BLI_stringenc(name, head, tail, numlen, val + 1);
+
+ }
+}
+
+
+/* ***************** INVENTOR ******************* */
+
+
+#define IV_MAXSTACK 500000
+#define IV_MAXFIELD 10
+#define IV_MAXCOL 16
+
+static float *iv_data_stack;
+static float ivcolors[IV_MAXCOL][3];
+static Object *ivsurf;
+static ListBase ivbase;
+
+struct IvNode {
+ struct IvNode *next, *prev;
+ char *nodename;
+ char *fieldname[IV_MAXFIELD];
+ int datalen[IV_MAXFIELD];
+ float *data[IV_MAXFIELD];
+};
+
+static int iv_curcol=0;
+
+static int iv_colornumber(struct IvNode *iv)
+{
+ float *fp, fr = 0.0, fg = 0.0, fb = 0.0;
+ int a;
+ char *cp;
+
+ /* terugzoeken naar laatste materiaal */
+ while(iv) {
+ if( strcmp(iv->nodename, "Material")==0) {
+ fp= iv->data[0];
+ if(fp==0) fp= iv->data[1];
+ if(fp) {
+ fr= fp[0];
+ fg= fp[1];
+ fb= fp[2];
+ }
+ break;
+ }
+ else if( strcmp(iv->nodename, "BaseColor")==0) {
+ fp= iv->data[0];
+ fr= fp[0];
+ fg= fp[1];
+ fb= fp[2];
+ break;
+ }
+ else if( strcmp(iv->nodename, "PackedColor")==0) {
+ cp= (char *)iv->data[0];
+ fr= cp[3]/255.0f;
+ fg= cp[2]/255.0f;
+ fb= cp[1]/255.0f;
+ break;
+ }
+ iv= iv->prev;
+
+ }
+ if(iv==0) return 0;
+ if(iv->datalen[0]<3) return 0;
+
+ for(a=0; a<iv_curcol; a++) {
+
+ if(ivcolors[a][0]== fr)
+ if(ivcolors[a][1]== fg)
+ if(ivcolors[a][2]== fb) return a+1
+ ;
+ }
+
+ if(a>=IV_MAXCOL) a= IV_MAXCOL-1;
+ iv_curcol= a+1;
+ ivcolors[a][0]= fr;
+ ivcolors[a][1]= fg;
+ ivcolors[a][2]= fb;
+
+ return iv_curcol;
+}
+
+static int iv_finddata(struct IvNode *iv, char *field, int fieldnr)
+{
+ /* zoek naar "field", tel lengte data en maak datablok. return skipdata */
+ float *fp;
+ int len, stackcount, skipdata=0;
+ char *cpa, terminator, str[64];
+ long i;
+
+ len= strlen(field);
+
+ cpa= iv->nodename+1;
+ while( *cpa != '}' ) {
+
+ if( *cpa == *field ) {
+ if( strncmp(cpa, field, len)==0 ) {
+ iv->fieldname[fieldnr]= cpa;
+
+ /* lezen tot aan eerste karakter */
+ cpa+= len;
+ skipdata+= len;
+ *cpa= 0;
+ cpa++;
+ skipdata++;
+
+ while( *cpa==32 || *cpa==13 || *cpa==10 || *cpa==9) cpa++;
+ if( *cpa=='[' ) {
+ terminator= ']';
+ cpa++;
+ skipdata++;
+ }
+ else terminator= 13;
+
+ stackcount= 0;
+ fp= iv_data_stack;
+
+ while( *cpa!=terminator && *cpa != '}' ) {
+
+ /* in fact, isdigit should include the dot and minus */
+ if( (isdigit(*cpa) || *cpa=='.' || *cpa=='-') && (isspace(cpa[-1]) || cpa[-1]==0 || cpa[-1]==',') ) {
+ if(cpa[1]=='x') {
+ memcpy(str, cpa, 16);
+ str[16]= 0;
+
+ sscanf(str, "%x", (int *)fp);
+ }
+ else {
+ /* atof doesn't stop after the first float
+ * in a long string at Windows... so we copy
+ * the float to a new string then atof... */
+
+ i=strpbrk(cpa, ", \n")-cpa;
+
+ if (i>63) *fp= 0.0;
+ else {
+ memcpy(str, cpa, i);
+ str[i]=0;
+
+ *fp= (float) atof(str);
+ }
+ }
+
+ stackcount++;
+ if(stackcount>=IV_MAXSTACK) {
+ printf("stackoverflow in IV read\n");
+ break;
+ }
+ fp++;
+ }
+ cpa++;
+ skipdata++;
+ }
+
+ iv->datalen[fieldnr]= stackcount;
+ if(stackcount) {
+ iv->data[fieldnr]= MEM_mallocN(sizeof(float)*stackcount, "iv_finddata");
+ memcpy(iv->data[fieldnr], iv_data_stack, sizeof(float)*stackcount);
+ }
+ else iv->data[fieldnr]= 0;
+
+ return skipdata;
+ }
+ }
+ cpa++;
+ skipdata++;
+ }
+
+ return skipdata;
+}
+
+static void read_iv_index(float *data, float *baseadr, float *index, int nr, int coordtype)
+{
+ /* in data schrijven: baseadr met offset index (aantal nr)*/
+ float *fp;
+ int ofs;
+
+ while(nr--) {
+ ofs= (int) *index;
+ fp= baseadr+coordtype*ofs;
+ VECCOPY(data, fp);
+ data+= 3;
+ index++;
+ }
+}
+
+
+
+static void read_inventor(char *str, struct ListBase *listb)
+{
+ struct IvNode *iv, *ivp, *ivn;
+ char *maindata, *md, *cpa;
+ float *index, *data, *fp;
+ int file, filelen, count, face, nr = 0;
+ int skipdata, ok, a, b, tot, first, colnr, coordtype, polytype, *idata;
+ struct DispList *dl;
+
+ ivbase.first= ivbase.last= 0;
+ iv_curcol= 0;
+ ivsurf= 0;
+
+ file= open(str, O_BINARY|O_RDONLY);
+ if(file== -1) {
+ error("Can't read file\n");
+ return;
+ }
+ filelen= BLI_filesize(file);
+
+ maindata= MEM_mallocN(filelen, "leesInventor");
+ read(file, maindata, filelen);
+ close(file);
+
+ iv_data_stack= MEM_mallocN(sizeof(float)*IV_MAXSTACK, "ivstack");
+
+ /* eerste preprocess: commentar eruit */
+ md= maindata+20;
+ count= 20;
+ while(count<filelen) {
+ if( *md=='#' ) { /* comment */
+ while( *md!=13 && *md!=10) { /* enters */
+ *md= 32;
+ md++;
+ count++;
+ if(count>=filelen) break;
+ }
+ }
+ md++;
+ count++;
+ }
+
+
+ /* we gaan alles ordenen: welke zijn de nodes en de fields? */
+ md= maindata;
+ count= 0;
+ while(count<filelen) {
+ if( *md=='{' ) { /* terug lezen */
+
+ cpa= md-1;
+ while( *cpa==32 || *cpa==13 || *cpa==10 || *cpa==9) { /* spaties/enters/tab weg */
+ *cpa= 0;
+ cpa--;
+ }
+
+ while( *cpa>32 && *cpa<128) cpa--;
+ cpa++;
+ *md= 0;
+
+ ok= 0;
+ skipdata= 0;
+ iv= MEM_callocN(sizeof(struct IvNode), "leesInventor");
+ iv->nodename= cpa;
+
+ if(strcmp(cpa, "Coordinate3")==0 || strcmp(cpa, "Coordinate4")==0) {
+ skipdata= iv_finddata(iv, "point", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "VertexProperty")==0) {
+ skipdata= iv_finddata(iv, "vertex", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "IndexedLineSet")==0) {
+ skipdata= iv_finddata(iv, "coordIndex", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "IndexedTriangleMesh")==0) {
+ skipdata= iv_finddata(iv, "coordIndex", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "IndexedFaceSet")==0) {
+ skipdata= iv_finddata(iv, "coordIndex", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "FaceSet")==0) {
+ skipdata= iv_finddata(iv, "numVertices", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "Material")==0) {
+ iv_finddata(iv, "diffuseColor", 0);
+ iv_finddata(iv, "ambientColor", 1);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "BaseColor")==0) {
+ iv_finddata(iv, "rgb", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "PackedColor")==0) {
+ iv_finddata(iv, "rgba", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "QuadMesh")==0) {
+ iv_finddata(iv, "verticesPerColumn", 0);
+ iv_finddata(iv, "verticesPerRow", 1);
+
+ ok= 1;
+ }
+ else if(strcmp(cpa, "IndexedTriangleStripSet")==0) {
+ skipdata= iv_finddata(iv, "coordIndex", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "TriangleStripSet")==0) {
+ skipdata= iv_finddata(iv, "numVertices", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "IndexedNurbsSurface")==0 || strcmp(cpa, "NurbsSurface")==0) {
+ iv_finddata(iv, "numUControlPoints", 0);
+ iv_finddata(iv, "numVControlPoints", 1);
+ iv_finddata(iv, "uKnotVector", 2);
+ iv_finddata(iv, "vKnotVector", 3);
+ ok= 1;
+ }
+ else {
+ /* naar 't einde */
+ while( *md != '}') {
+ md++;
+ count++;
+ if(count<filelen) break;
+ }
+ }
+
+
+ if(ok) {
+ BLI_addtail(&ivbase, iv);
+ md+= skipdata;
+ count+= skipdata;
+ }
+ else MEM_freeN(iv);
+
+ }
+ md++;
+ count++;
+ }
+
+ /* nodes samenvoegen */
+ iv= ivbase.first;
+
+ while(iv) {
+ ivn= iv->next;
+
+ if( strncmp(iv->nodename, "Indexed", 7)==0) {
+ /* terugzoeken: zelfde naam? */
+
+ ivp= iv->prev;
+ while(ivp) {
+ if(strcmp(iv->nodename, ivp->nodename)==0) break;
+
+ if(strcmp(ivp->nodename, "Coordinate3")==0 ||
+ strcmp(ivp->nodename, "Coordinate4")==0 ||
+ strcmp(ivp->nodename, "VertexProperty")==0) {
+ ivp= 0;
+ break;
+ }
+ ivp= ivp->prev;
+ }
+
+ if(ivp) {
+ /* iv bij ivp voegen */
+
+ tot= iv->datalen[0] + ivp->datalen[0];
+ if(tot) {
+ data= MEM_mallocN(tot*sizeof(float), "samenvoeg iv");
+ memcpy(data, ivp->data[0], sizeof(float)*ivp->datalen[0]);
+ memcpy(data+ivp->datalen[0], iv->data[0], sizeof(float)*iv->datalen[0]);
+
+ ivp->datalen[0]+= iv->datalen[0];
+ MEM_freeN(ivp->data[0]);
+ ivp->data[0]= data;
+
+ BLI_remlink(&ivbase, iv);
+ MEM_freeN(iv->data[0]);
+ MEM_freeN(iv);
+ }
+ }
+ }
+
+ iv= ivn;
+ }
+
+
+ /* Nodes omzetten naar DispLists */
+ iv= ivbase.first;
+ while(iv) {
+
+ /* printf(" Node: %s\n", iv->nodename); */
+ /* if(iv->fieldname[0]) printf(" Field: %s len %d\n", iv->fieldname[0], iv->datalen[0]); */
+ coordtype= 3;
+
+ if( strcmp(iv->nodename, "IndexedLineSet")==0 ) {
+
+ colnr= iv_colornumber(iv);
+
+ /* terugzoeken naar data */
+ ivp= iv;
+ while(ivp->prev) {
+ ivp= ivp->prev;
+ if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
+ coordtype= 4;
+ break;
+ }
+ }
+ if(ivp) {
+
+ /* tel het aantal lijnen */
+ tot= 0;
+ index= iv->data[0];
+ for(a=0; a<iv->datalen[0]-1; a++) {
+ if(index[0]!= -1 && index[1]!= -1) tot++;
+ index++;
+ }
+
+ tot*= 2; /* aantal vertices */
+ dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor1");
+ BLI_addtail(listb, dl);
+ dl->type= DL_SEGM;
+ dl->nr= 2;
+ dl->parts= tot/2;
+ dl->col= colnr;
+ data= (float *)(dl+1);
+
+ index= iv->data[0];
+ for(a=0; a<iv->datalen[0]-1; a++) {
+ if(index[0]!= -1 && index[1]!= -1) {
+ read_iv_index(data, ivp->data[0], index, 2, coordtype);
+ data+= 6;
+ }
+ index++;
+ }
+ }
+ }
+ else if( strcmp(iv->nodename, "FaceSet")==0 ) {
+
+ colnr= iv_colornumber(iv);
+
+ /* terugzoeken naar data */
+ ivp= iv;
+ while(ivp->prev) {
+ ivp= ivp->prev;
+ if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
+ coordtype= 4;
+ break;
+ }
+ }
+
+ if(ivp) {
+ /* tel het aantal driehoeken */
+ tot= 0;
+
+ index= iv->data[0];
+ polytype= (int) index[0];
+
+ for(a=0; a<iv->datalen[0]; a++) {
+ if(index[0]== polytype) tot++; /* een soort? */
+ index++;
+ }
+
+
+ tot*= polytype; /* aantal vertices */
+ dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor4");
+ BLI_addtail(listb, dl);
+ dl->type= DL_POLY;
+ dl->nr= polytype;
+ dl->parts= tot/polytype;
+ dl->col= colnr;
+ data= (float *)(dl+1);
+
+ index= ivp->data[0];
+ first= 1;
+ for(a=0; a<iv->datalen[0]; a++) {
+
+ VECCOPY(data, index);
+ data+= 3;
+ index+= 3;
+
+ VECCOPY(data, index);
+ data+= 3;
+ index+= 3;
+
+ VECCOPY(data, index);
+ data+= 3;
+ index+= 3;
+
+ if(polytype==4) {
+ VECCOPY(data, index);
+ data+= 3;
+ index+= 3;
+ }
+ }
+ }
+ }
+ else if( strcmp(iv->nodename, "TriangleStripSet")==0 ) {
+
+ colnr= iv_colornumber(iv);
+
+ /* terugzoeken naar data */
+ ivp= iv;
+ while(ivp->prev) {
+ ivp= ivp->prev;
+ if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
+ coordtype= 4;
+ break;
+ }
+ }
+
+ if(ivp) {
+ /* tel het aantal driehoeken */
+ tot= 0;
+ face= 0;
+
+ index= iv->data[0]; /* afmeting strip */
+
+ for(a=0; a<iv->datalen[0]; a++) {
+ tot+= (int) index[0];
+ face+= ((int) index[0]) - 2;
+ index++;
+ }
+
+ dl= MEM_callocN(sizeof(struct DispList), "leesInventor4");
+ dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts");
+ dl->index= MEM_callocN( face*3*sizeof(int), "dl index");
+
+ dl->type= DL_INDEX3;
+ dl->nr= tot;
+ dl->parts= face;
+
+ BLI_addtail(listb, dl);
+ dl->col= colnr;
+
+ index= iv->data[0]; /* afmeting strip */
+ fp= ivp->data[0]; /* vertices */
+ data= dl->verts;
+ idata= dl->index;
+ first= 0;
+
+ for(a=0; a<iv->datalen[0]; a++) {
+
+ /* vertices */
+ for(b=0; b<index[0]; b++) {
+ VECCOPY(data, fp);
+ data+= 3;
+ fp+= coordtype;
+ }
+
+ /* indices */
+ for(b=0; b<index[0]-2; b++) {
+ idata[0]= first;
+ idata[1]= first+1;
+ idata[2]= first+2;
+ first++;
+ idata+= 3;
+ }
+ first+= 2;
+
+ index++;
+ }
+ }
+ }
+ else if( strcmp(iv->nodename, "IndexedFaceSet")==0 ) {
+
+ colnr= iv_colornumber(iv);
+
+ /* terugzoeken naar data */
+ ivp= iv;
+ while(ivp->prev) {
+ ivp= ivp->prev;
+ if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
+ coordtype= 4;
+ break;
+ }
+ }
+ if(ivp) {
+
+ /* tel het aantal driehoeken */
+ face= 0;
+ index= iv->data[0];
+ for(a=0; a<iv->datalen[0]-2; a++) {
+ if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++;
+ index++;
+ }
+
+ /* aantal vertices */
+ tot= ivp->datalen[0]/coordtype;
+
+ if(tot) {
+ dl= MEM_callocN(sizeof(struct DispList), "leesInventor5");
+ BLI_addtail(listb, dl);
+ dl->type= DL_INDEX3;
+ dl->nr= tot;
+ dl->parts= face;
+ dl->col= colnr;
+
+ dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts");
+ dl->index= MEM_callocN(sizeof(int)*3*face, "dl index");
+
+ /* vertices */
+ fp= ivp->data[0];
+ data= dl->verts;
+ for(b=tot; b>0; b--) {
+ VECCOPY(data, fp);
+ data+= 3;
+ fp+= coordtype;
+ }
+
+ /* indices */
+ index= iv->data[0];
+ idata= dl->index;
+ first= 1;
+
+ for(a=0; a<iv->datalen[0]-2; a++) {
+
+ if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) {
+
+ /* deze truuk is om poly's met meer dan 3 vertices correct te vullen */
+ if(first) {
+ nr= (int) index[0];
+ first= 0;
+ }
+ idata[0]= nr;
+ idata[1]= (int) index[1];
+ idata[2]= (int) index[2];
+ idata+= 3;
+ }
+ else first= 1;
+
+ index++;
+ }
+ }
+ }
+ }
+ else if( strcmp(iv->nodename, "IndexedTriangleMesh")==0 ||
+ strcmp(iv->nodename, "IndexedTriangleStripSet")==0 ) {
+
+ colnr= iv_colornumber(iv);
+
+ /* terugzoeken naar data */
+ ivp= iv;
+ while(ivp->prev) {
+ ivp= ivp->prev;
+ if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
+ coordtype= 4;
+ break;
+ }
+ }
+ if(ivp) {
+
+ /* tel het aantal driehoeken */
+ face= 0;
+ index= iv->data[0];
+ for(a=0; a<iv->datalen[0]-2; a++) {
+ if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++;
+ index++;
+ }
+
+ /* aantal vertices */
+ tot= ivp->datalen[0]/coordtype;
+
+ dl= MEM_callocN(sizeof(struct DispList), "leesInventor6");
+ BLI_addtail(listb, dl);
+ dl->type= DL_INDEX3;
+ dl->nr= tot;
+ dl->parts= face;
+ dl->col= colnr;
+
+ dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts");
+ dl->index= MEM_callocN(sizeof(int)*3*face, "dl index");
+
+ /* vertices */
+ fp= ivp->data[0];
+ data= dl->verts;
+ for(b=tot; b>0; b--) {
+ VECCOPY(data, fp);
+ data+= 3;
+ fp+= coordtype;
+ }
+
+ /* indices */
+ index= iv->data[0];
+ idata= dl->index;
+
+ for(a=iv->datalen[0]-2; a>0; a--) {
+
+ if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) {
+ idata[0]= (int) index[0];
+ idata[1]= (int) index[1];
+ idata[2]= (int) index[2];
+ idata+= 3;
+ }
+ index++;
+ }
+ }
+ }
+ else if( strcmp(iv->nodename, "QuadMesh")==0 ) {
+
+ colnr= iv_colornumber(iv);
+
+ /* terugzoeken naar data */
+ ivp= iv;
+ while(ivp->prev) {
+ ivp= ivp->prev;
+ if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "VertexProperty")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
+ coordtype= 4;
+ break;
+ }
+ }
+
+ if(ivp) {
+ tot= (int) (floor(*(iv->data[0])+0.5) * floor(*(iv->data[1])+0.5));
+
+ if(tot>0) {
+ dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor8");
+ BLI_addtail(listb, dl);
+ dl->type= DL_SURF;
+ dl->parts= (int) floor(*(iv->data[0])+0.5);
+ dl->nr= (int) floor(*(iv->data[1])+0.5);
+ dl->col= colnr;
+ data= (float *)(dl+1);
+ memcpy(data, ivp->data[0], tot*3*sizeof(float));
+ }
+ }
+ }
+ else if(strcmp(iv->nodename, "IndexedNurbsSurface")==0 || strcmp(iv->nodename, "NurbsSurface")==0) {
+
+ colnr= iv_colornumber(iv);
+
+ /* terugzoeken naar data */
+ ivp= iv;
+ while(ivp->prev) {
+ ivp= ivp->prev;
+ if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
+ coordtype= 4;
+ break;
+ }
+ }
+ if(ivp) {
+ a= (int) *(iv->data[0]);
+ b= (int) *(iv->data[1]);
+
+ tot= a*b;
+
+ if( (a>=4 || b>=4) && tot>6) {
+ Object *ob;
+ Curve *cu;
+ Nurb *nu;
+ BPoint *bp;
+
+ if(ivsurf==0) {
+ ob= add_object(OB_SURF);
+ ivsurf= ob;
+ }
+ else ob= ivsurf;
+ cu= ob->data;
+ nu = (Nurb*) MEM_callocN(sizeof(Nurb),"addNurbprim") ;
+ BLI_addtail(&cu->nurb, nu);
+ nu->type= CU_NURBS;
+
+ nu->pntsu= a;
+ nu->pntsv= b;
+ nu->resolu= 2*a;
+ nu->resolv= 2*b;
+
+ nu->flagu= 0;
+ nu->flagv= 0;
+
+ nu->bp = bp =
+ (BPoint*)MEM_callocN(tot * sizeof(BPoint), "addNurbprim3");
+ a= tot;
+ data= ivp->data[0];
+ while(a--) {
+ VECCOPY(bp->vec, data);
+ if(coordtype==4) {
+ bp->vec[3]= data[3];
+ VecMulf(bp->vec, 1.0f/data[3]);
+ }
+ else bp->vec[3]= 1.0;
+ data+= coordtype;
+ bp++;
+ }
+
+ /* iv->datalen[2] / [3] is aantal knots */
+ nu->orderu= iv->datalen[2] - nu->pntsu;
+ nu->orderv= iv->datalen[3] - nu->pntsv;
+
+ nu->knotsu= MEM_mallocN( sizeof(float)*(iv->datalen[2]), "knots");
+ memcpy(nu->knotsu, iv->data[2], sizeof(float)*(iv->datalen[2]));
+ nu->knotsv= MEM_mallocN( sizeof(float)*(iv->datalen[3]), "knots");
+ memcpy(nu->knotsv, iv->data[3], sizeof(float)*(iv->datalen[3]));
+
+ switchdirectionNurb(nu);
+
+ }
+ else {
+ dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor3");
+ BLI_addtail(listb, dl);
+ dl->type= DL_SURF;
+ dl->nr= (int) *(iv->data[0]);
+ dl->parts= (int) *(iv->data[1]);
+ dl->col= colnr;
+ data= (float *)(dl+1);
+
+ a= tot;
+ fp= ivp->data[0];
+ while(a--) {
+ VECCOPY(data, fp);
+ fp+= coordtype;
+ data+= 3;
+ }
+ }
+ }
+ }
+ iv= iv->next;
+ }
+
+ /* vrijgeven */
+ iv= ivbase.first;
+ while(iv) {
+ for(a=0; a<IV_MAXFIELD; a++) {
+ if(iv->data[a]) MEM_freeN(iv->data[a]);
+ }
+ iv= iv->next;
+ }
+
+ BLI_freelistN(&ivbase);
+ MEM_freeN(maindata);
+ MEM_freeN(iv_data_stack);
+
+}
+
+/* ************************************************************ */
+
+static void displist_to_mesh(DispList *dlfirst)
+{
+ Object *ob;
+ Mesh *me;
+ Material *ma;
+ DispList *dl;
+ MVert *mvert;
+ MFace *mface;
+ float *data, vec[3], min[3], max[3];
+ int a, b, startve, *idata, totedge=0, tottria=0, totquad=0, totvert=0, totvlak, totcol=0, colnr;
+ int p1, p2, p3, p4;
+
+ /* eerst tellen */
+ INIT_MINMAX(min, max);
+
+ dl= dlfirst;
+ while(dl) {
+
+ /* PATCH 1 (polyfill) kan hier niet, er wordt geen listbase meegegeven. eerder doen! */
+ /* PATCH 2 */
+ if(dl->type==DL_SEGM && dl->nr>2) {
+ data= (float *)(dl+1);
+ if(data[0]==data[3*(dl->nr-1)]) {
+ if(data[1]==data[3*(dl->nr-1)+1]) {
+ if(data[2]==data[3*(dl->nr-1)+2]) {
+ dl->type= DL_POLY;
+ dl->nr--;
+ }
+ }
+ }
+ }
+
+ /* kleuren */
+ if(dl->col > totcol) totcol= dl->col;
+
+ /* afmeting en tellen */
+ if(dl->type==DL_SURF) {
+ a= dl->nr;
+ b= dl->parts;
+ if(dl->flag & 1) a++;
+ if(dl->flag & 2) b++;
+
+ totquad+= a*b;
+
+ totvert+= dl->nr*dl->parts;
+
+ data= (float *)(dl+1);
+ for(a= dl->nr*dl->parts; a>0; a--) {
+ DO_MINMAX(data, min, max);
+ data+= 3;
+ }
+ }
+ else if(dl->type==DL_POLY) {
+ if(dl->nr==3 || dl->nr==4) {
+ if(dl->nr==3) tottria+= dl->parts;
+ else totquad+= dl->parts;
+
+ totvert+= dl->nr*dl->parts;
+
+ data= (float *)(dl+1);
+ for(a= dl->nr*dl->parts; a>0; a--) {
+ DO_MINMAX(data, min, max);
+ data+= 3;
+ }
+ }
+ else if(dl->nr>4) {
+
+ tottria+= dl->nr*dl->parts;
+ totvert+= dl->nr*dl->parts;
+
+ data= (float *)(dl+1);
+ for(a= dl->nr*dl->parts; a>0; a--) {
+ DO_MINMAX(data, min, max);
+ data+= 3;
+ }
+
+ }
+ }
+ else if(dl->type==DL_INDEX3) {
+ tottria+= dl->parts;
+ totvert+= dl->nr;
+
+ data= dl->verts;
+ for(a= dl->nr; a>0; a--) {
+ DO_MINMAX(data, min, max);
+ data+= 3;
+ }
+ }
+ else if(dl->type==DL_SEGM) {
+
+ tottria+= (dl->nr-1)*dl->parts;
+ totvert+= dl->nr*dl->parts;
+
+ data= (float *)(dl+1);
+ for(a= dl->nr*dl->parts; a>0; a--) {
+ DO_MINMAX(data, min, max);
+ data+= 3;
+ }
+ }
+
+ dl= dl->next;
+ }
+
+ if(totvert==0) {
+ return;
+ }
+ if(totvert>=65000 || tottria>=65000) {
+ if (totvert>=65000) {
+ error("Too many vertices (%d)", totvert);
+ } else {
+ error("Too many faces (%d)", tottria);
+ }
+
+ return;
+ }
+
+ if(totcol>16) {
+ error("Found more than 16 different colors");
+ totcol= 16;
+ }
+
+ vec[0]= (min[0]+max[0])/2;
+ vec[1]= (min[1]+max[1])/2;
+ vec[2]= (min[2]+max[2])/2;
+
+ ob= add_object(OB_MESH);
+ VECCOPY(ob->loc, vec);
+ where_is_object(ob);
+
+ me= ob->data;
+
+ /* kleuren */
+ if(totcol) {
+ ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat");
+ me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat");
+ me->totcol= totcol;
+ ob->totcol= (unsigned char) me->totcol;
+ ob->actcol= 1;
+ }
+
+ /* materialen */
+ for(a=0; a<totcol; a++) {
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->mtex[0]==0) {
+ if(ivcolors[a][0]==ma->r && ivcolors[a][1]==ma->g && ivcolors[a][2]==ma->b) {
+ me->mat[a]= ma;
+ ma->id.us++;
+ break;
+ }
+ }
+ ma= ma->id.next;
+ }
+ if(ma==0) {
+ ma= add_material("ext");
+ me->mat[a]= ma;
+ ma->r= ivcolors[a][0];
+ ma->g= ivcolors[a][1];
+ ma->b= ivcolors[a][2];
+ automatname(ma);
+ }
+ }
+
+ totvlak= totquad+tottria+totedge;
+
+ printf("Import: %d vertices %d faces\n", totvert, totvlak);
+
+ if(totvert) me->mvert= MEM_callocN(totvert*sizeof(MVert), "mvert");
+ if(totvlak) me->mface= MEM_callocN(totvlak*sizeof(MFace), "mface");
+ me->totvert= totvert;
+ me->totface= totvlak;
+
+ mvert= me->mvert;
+ mface= me->mface;
+
+ startve= 0;
+
+ dl= dlfirst;
+ while(dl) {
+
+ colnr= (dl->col>15 ? 15: dl->col);
+ if(colnr) colnr--;
+
+ if(dl->type==DL_SURF) {
+ data= (float *)(dl+1);
+
+ for(a=dl->parts*dl->nr; a>0; a--) {
+ mvert->co[0]= data[0] -vec[0];
+ mvert->co[1]= data[1] -vec[1];
+ mvert->co[2]= data[2] -vec[2];
+
+ data+=3;
+ mvert++;
+ }
+
+ for(a=0; a<dl->parts; a++) {
+
+ DL_SURFINDEX(dl->flag & 1, dl->flag & 2, dl->nr, dl->parts);
+ p1+= startve;
+ p2+= startve;
+ p3+= startve;
+ p4+= startve;
+
+ for(; b<dl->nr; b++) {
+
+ mface->v1= p1;
+ mface->v2= p2;
+ mface->v3= p4;
+ mface->v4= p3;
+
+ mface->mat_nr= colnr;
+ test_index_mface(mface, 4);
+
+ mface++;
+
+ p4= p3;
+ p3++;
+ p2= p1;
+ p1++;
+ }
+ }
+
+ startve += dl->parts*dl->nr;
+
+ }
+ else if(dl->type==DL_POLY) {
+
+ if(dl->nr==3 || dl->nr==4) {
+ data= (float *)(dl+1);
+
+ for(a=dl->parts*dl->nr; a>0; a--) {
+ mvert->co[0]= data[0] -vec[0];
+ mvert->co[1]= data[1] -vec[1];
+ mvert->co[2]= data[2] -vec[2];
+ data+=3;
+ mvert++;
+ }
+
+ for(a=0; a<dl->parts; a++) {
+ if(dl->nr==3) {
+ mface->v1= startve+a*dl->nr;
+ mface->v2= startve+a*dl->nr+1;
+ mface->v3= startve+a*dl->nr+2;
+ mface->mat_nr= colnr;
+ test_index_mface(mface, 3);
+ mface++;
+ }
+ else {
+ mface->v1= startve+a*dl->nr;
+ mface->v2= startve+a*dl->nr+1;
+ mface->v3= startve+a*dl->nr+2;
+ mface->v4= startve+a*dl->nr+3;
+ mface->mat_nr= colnr;
+ test_index_mface(mface, 4);
+ mface++;
+ }
+ }
+ startve += dl->parts*dl->nr;
+ }
+ else if(dl->nr>4) {
+ data= (float *)(dl+1);
+
+ for(a=dl->parts*dl->nr; a>0; a--) {
+ mvert->co[0]= data[0] -vec[0];
+ mvert->co[1]= data[1] -vec[1];
+ mvert->co[2]= data[2] -vec[2];
+
+ data+=3;
+ mvert++;
+ }
+
+ for(b=0; b<dl->parts; b++) {
+ for(a=0; a<dl->nr; a++) {
+ mface->v1= startve+a;
+
+ if(a==dl->nr-1) mface->v2= startve;
+ else mface->v2= startve+a+1;
+
+ mface->mat_nr= colnr;
+ test_index_mface(mface, 2);
+
+ mface++;
+ }
+ startve += dl->nr;
+ }
+ }
+ }
+ else if(dl->type==DL_INDEX3) {
+ data= dl->verts;
+
+ for(a=dl->nr; a>0; a--) {
+ mvert->co[0]= data[0] -vec[0];
+ mvert->co[1]= data[1] -vec[1];
+ mvert->co[2]= data[2] -vec[2];
+ data+=3;
+ mvert++;
+ }
+
+ idata= dl->index;
+ for(b=dl->parts; b>0; b--) {
+ mface->v1= startve+idata[0];
+ mface->v2= startve+idata[1];
+ mface->v3= startve+idata[2];
+ mface->mat_nr= colnr;
+
+ if (mface->v1>me->totvert-1) mface->v1= me->totvert-1;
+ if (mface->v2>me->totvert-1) mface->v2= me->totvert-1;
+ if (mface->v3>me->totvert-1) mface->v3= me->totvert-1;
+
+ test_index_mface(mface, 3);
+ mface++;
+ idata+= 3;
+ }
+ startve += dl->nr;
+ }
+ else if(dl->type==DL_SEGM) {
+ data= (float *)(dl+1);
+
+ for(a=dl->parts*dl->nr; a>0; a--) {
+ mvert->co[0]= data[0] -vec[0];
+ mvert->co[1]= data[1] -vec[1];
+ mvert->co[2]= data[2] -vec[2];
+ data+=3;
+ mvert++;
+ }
+
+ for(b=0; b<dl->parts; b++) {
+ for(a=0; a<dl->nr-1; a++) {
+ mface->v1= startve+a;
+ mface->v2= startve+a+1;
+ mface->mat_nr= colnr;
+ test_index_mface(mface, 2);
+ mface++;
+ }
+ startve += dl->nr;
+ }
+ }
+ dl= dl->next;
+ }
+
+ G.obedit= ob;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+
+ G.obedit= 0;
+ tex_space_mesh(me);
+
+}
+
+static void displist_to_objects(ListBase *lbase)
+{
+ DispList *dl, *first, *prev, *next;
+ ListBase tempbase;
+ int maxaantal, curcol, totvert=0, vert;
+
+ /* eerst dit: is nu nog actief */
+ if(ivsurf) {
+ where_is_object(ivsurf);
+ docentre_new();
+ }
+
+ dl= lbase->first;
+ while(dl) {
+ next= dl->next;
+
+ /* PATCH 1: polyfill */
+ if(dl->type==DL_POLY && dl->nr>4) {
+ /* oplossing: bij elkaar in aparte listbase zetten */
+ ;
+ }
+ /* PATCH 2: poly's van 2 punten */
+ if(dl->type==DL_POLY && dl->nr==2) dl->type= DL_SEGM;
+
+ dl= next;
+ }
+
+ /* vertices tellen */
+
+ dl= lbase->first;
+ while(dl) {
+
+ if(dl->type==DL_SURF) totvert+= dl->nr*dl->parts;
+ else if(dl->type==DL_POLY) {
+ if(dl->nr==3 || dl->nr==4) totvert+= dl->nr*dl->parts;
+ else if(dl->nr>4) totvert+= dl->nr*dl->parts;
+ }
+ else if(dl->type==DL_INDEX3) totvert+= dl->nr;
+ else if(dl->type==DL_SEGM) totvert+= dl->nr*dl->parts;
+
+ dl= dl->next;
+ }
+
+ if(totvert==0) {
+
+ if(ivsurf==0) error("Found no data");
+ if(lbase->first) BLI_freelistN(lbase);
+
+ return;
+ }
+
+ maxaantal= 32000;
+
+ if(totvert>maxaantal) {
+
+ /* probeer kleuren bij elkaar te zetten */
+ curcol= 0;
+ tempbase.first= tempbase.last= 0;
+
+ while(lbase->first) {
+ dl= lbase->first;
+ while(dl) {
+ next= dl->next;
+ if(dl->col==curcol) {
+ BLI_remlink(lbase, dl);
+ BLI_addtail(&tempbase, dl);
+ dl->col= 0;
+ }
+
+ dl= next;
+ }
+
+ /* in tempbase zitten alle kleuren 'curcol' */
+ totvert= 0;
+ dl= first= tempbase.first;
+ while(dl) {
+ vert= 0;
+
+ if(dl->type==DL_SURF) vert= dl->nr*dl->parts;
+ else if(dl->type==DL_POLY) {
+ if(dl->nr==3 || dl->nr==4) vert= dl->nr*dl->parts;
+ else if(dl->nr>4) vert= dl->nr*dl->parts;
+ }
+ else if(dl->type==DL_INDEX3) totvert+= dl->nr;
+ else if(dl->type==DL_SEGM) vert= dl->nr*dl->parts;
+
+ totvert+= vert;
+ if(totvert > maxaantal || dl->next==0) {
+ if(dl->next==0) {
+ displist_to_mesh(first);
+ }
+ else if(dl->prev) {
+ prev= dl->prev;
+ prev->next= 0;
+ displist_to_mesh(first);
+ prev->next= dl;
+ first= dl;
+ totvert= 0;
+ }
+ }
+
+ dl= dl->next;
+ }
+
+ freedisplist(&tempbase);
+
+ curcol++;
+ }
+ }
+ else displist_to_mesh(lbase->first);
+
+ freedisplist(lbase);
+
+}
+
+int BKE_read_exotic(char *name)
+{
+ ListBase lbase={0, 0};
+ int file, len;
+ char str[32];
+ int *s0 = (int*) str;
+ int retval = 0;
+
+ // make sure we're not trying to read a directory....
+
+ len= strlen(name);
+ if (name[len-1] !='/' && name[len-1] != '\\') {
+ file = open(name, O_BINARY|O_RDONLY);
+
+ if (file <= 0) {
+ error("Can't open file: %s", name);
+ } else {
+ read(file, str, 31);
+ close(file);
+
+ if ((*s0 != FORM) && (strncmp(str, "BLEN", 4) != 0)) {
+
+ waitcursor(1);
+
+ if(*s0==GOUR) {
+ if(G.obedit) {
+ error("Unable to perform function in EditMode");
+ } else {
+ read_radiogour(name);
+ retval = 1;
+ }
+ }
+ else if ELEM4(*s0, DDG1, DDG2, DDG3, DDG4) {
+ if(G.obedit) {
+ error("Unable to perform function in EditMode");
+ } else {
+ read_videoscape(name);
+ retval = 1;
+ }
+ }
+ else if(strncmp(str, "#Inventor V1.0", 14)==0) {
+ if( strncmp(str+15, "ascii", 5)==0) {
+ read_inventor(name, &lbase);
+ displist_to_objects(&lbase);
+ retval = 1;
+ } else {
+ error("Can only read Inventor 1.0 ascii");
+ }
+ }
+ else if((strncmp(str, "#VRML V1.0 asc", 14)==0)) {
+ read_inventor(name, &lbase);
+ displist_to_objects(&lbase);
+ retval = 1;
+ }
+ else if(is_dxf(name)) {
+ dxf_read(name);
+ retval = 1;
+ }
+ // TODO: this should not be in the kernel...
+ else { // unknown format, call Python importloader
+ if (BPY_call_importloader(name)) {
+ retval = 1;
+ } else {
+ error("Unknown file type or error, check console");
+ }
+
+ }
+ waitcursor(0);
+ }
+ }
+ }
+
+ if (retval == 1) {
+ strcpy(G.sce, name);
+ }
+
+ return (retval);
+}
+
+
+/* ************************ WRITE ************************** */
+
+
+char videosc_dir[160]= {0, 0};
+
+
+static void write_videoscape_mesh(Object *ob, char *str)
+{
+ Mesh *me;
+ Material *ma;
+ MVert *mvert;
+ MFace *mface;
+ FILE *fp;
+ EditVert *eve;
+ EditVlak *evl;
+ unsigned int kleur[32];
+ float co[3];
+ int a;
+ long tot;
+ char *cp;
+
+ if(ob && ob->type==OB_MESH);
+ else {
+ return;
+ }
+
+ kleur[0]= 0x00C0C0C0;
+ if(G.order==L_ENDIAN) SWITCH_INT(kleur[0]);
+
+ cp= (char *)kleur;
+ for(a=0; a<ob->totcol; a++, cp+=4) {
+
+ ma= give_current_material(ob, a+1);
+ if(ma) {
+ cp[0]= (unsigned char) (255.0*ma->emit);
+ cp[1]= (unsigned char) (255.0*ma->b);
+ cp[2]= (unsigned char) (255.0*ma->g);
+ cp[3]= (unsigned char) (255.0*ma->r);
+ }
+ else kleur[a]= 0x00C0C0C0;
+
+ if(G.order==L_ENDIAN) SWITCH_INT(kleur[a]);
+
+ if(a>30) break;
+ }
+
+ fp= fopen(str, "wb");
+ if(fp==NULL) return;
+
+ fprintf(fp,"3DG1\n");
+
+ if(G.obedit) {
+
+ fprintf(fp, "%d\n", G.totvert);
+
+ tot= 0;
+ eve= G.edve.first;
+ while(eve) {
+ VECCOPY(co, eve->co);
+ Mat4MulVecfl(ob->obmat, co);
+ fprintf(fp, "%f %f %f\n", co[0], co[1], co[2] );
+ eve->vn= (struct EditVert *)tot;
+ tot++;
+ eve= eve->next;
+ }
+ evl= G.edvl.first;
+ while(evl) {
+
+ if(evl->v4==0) {
+ fprintf(fp, "3 %p %p %p 0x%x\n", evl->v1->vn, evl->v2->vn, evl->v3->vn, kleur[evl->mat_nr]);
+ }
+ else {
+ fprintf(fp, "4 %p %p %p %p 0x%x\n", evl->v1->vn, evl->v2->vn, evl->v3->vn, evl->v4->vn, kleur[evl->mat_nr]);
+ }
+ evl= evl->next;
+ }
+ }
+ else {
+ DispList *dl;
+ float *extverts=0;
+
+ dl= find_displist(&ob->disp, DL_VERTS);
+ if(dl) extverts= dl->verts;
+
+ me= ob->data;
+
+ fprintf(fp, "%d\n", me->totvert);
+
+ mvert= me->mvert;
+ mface= me->mface;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ if(extverts) {
+ VECCOPY(co, extverts);
+ extverts+= 3;
+ }
+ else {
+ VECCOPY(co, mvert->co);
+ }
+ Mat4MulVecfl(ob->obmat, co);
+ fprintf(fp, "%f %f %f\n", co[0], co[1], co[2] );
+ }
+ for(a=0; a<me->totface; a++, mface++) {
+ if(mface->v3==0) {
+ fprintf(fp, "2 %d %d 0x%x\n", mface->v1, mface->v2, kleur[mface->mat_nr]);
+ }
+ else if(mface->v4==0) {
+ fprintf(fp, "3 %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, kleur[mface->mat_nr]);
+ }
+ else {
+ fprintf(fp, "4 %d %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, mface->v4, kleur[mface->mat_nr]);
+ }
+ }
+ }
+
+ fclose(fp);
+
+}
+
+
+void write_videoscape(char *str)
+{
+ Base *base;
+ int file, val, lampdone=0;
+ unsigned short numlen;
+ char head[FILE_MAXFILE], tail[FILE_MAXFILE];
+
+ if(BLI_testextensie(str,".trace")) str[ strlen(str)-6]= 0;
+ if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
+ if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
+ if(BLI_testextensie(str,".obj")==0) strcat(str, ".obj");
+
+ file= open(str,O_BINARY|O_RDONLY);
+ close(file);
+ if(file>-1) if(saveover(str)==0) return;
+
+ strcpy(videosc_dir, str);
+
+ base= G.scene->base.first;
+ while(base) {
+ if((base->flag & SELECT) && (base->lay & G.scene->lay)) {
+ if(base->object->type==OB_MESH) {
+ write_videoscape_mesh(base->object, str);
+ val = BLI_stringdec(str, head, tail, &numlen);
+ BLI_stringenc(str, head, tail, numlen, val + 1);
+ }
+ else if(base->object->type==OB_CURVE || base->object->type==OB_SURF) {
+ /* write_videoscape_nurbs(base->object, str); */
+ /* val = stringdec(str, head, tail, &numlen); */
+ /* stringenc(str, head, tail, numlen, val + 1); */
+ }
+ else if(lampdone==0 && base->object->type==OB_LAMP) {
+ /* lampdone= 1; */
+ /* write_videoscape_lamps(str); */
+ /* val = stringdec(str, head, tail, &numlen); */
+ /* stringenc(str, head, tail, numlen, val + 1); */
+ }
+ }
+ base= base->next;
+ }
+
+
+ /* weggooien als nog hogere nummers bestaan */
+ while(remove(str)==0) {
+
+ val = BLI_stringdec(str, head, tail, &numlen);
+ BLI_stringenc(str, head, tail, numlen, val + 1);
+ }
+}
+
+/* ******************************* WRITE VRML ***************************** */
+
+static void replace_chars(char *str1, char *str2)
+{
+ int a= strlen(str2);
+
+ str1[a]= 0;
+ while(a--) {
+ if(str2[a]=='.' || str2[a]==' ') str1[a]= '_';
+ else str1[a]= str2[a];
+ }
+}
+
+
+static void write_material_vrml(FILE *fp, Material *ma)
+{
+ char str[32];
+
+ replace_chars(str, ma->id.name+2);
+
+ fprintf(fp, "\tDEF %s\n", str);
+ fprintf(fp, "\tMaterial {\n");
+
+ fprintf(fp, "\t\tdiffuseColor %f %f %f\n", ma->r, ma->g, ma->b);
+ fprintf(fp, "\t\tspecularColor %f %f %f\n", ma->specr, ma->specg, ma->specb);
+ fprintf(fp, "\t\tshininess %f \n", ((float)ma->har)/100.0);
+ fprintf(fp, "\t\ttransparency %f \n", 1.0-ma->alpha);
+
+ fprintf(fp, "\t}\n");
+
+}
+
+unsigned int *mcol_to_vcol(Mesh *me)
+{
+ MFace *mface;
+ unsigned int *mcol, *mcoln, *mcolmain;
+ int a;
+
+ if(me->totface==0 || me->mcol==0) return 0;
+
+ mcoln= mcolmain= MEM_mallocN(sizeof(int)*me->totvert, "mcoln");
+ mcol = (unsigned int *)me->mcol;
+ mface= me->mface;
+
+ for(a=me->totface; a>0; a--, mface++) {
+ mcoln[mface->v1]= mcol[0];
+ mcoln[mface->v2]= mcol[1];
+ if(mface->v3) mcoln[mface->v3]= mcol[2];
+ if(mface->v4) mcoln[mface->v4]= mcol[3];
+
+ mcol+= 4;
+ }
+
+ return mcolmain;
+}
+
+void mcol_to_rgba(unsigned int col, float *r, float *g, float *b, float *a)
+{
+ char *cp;
+
+ cp = (char *)&col;
+
+ *r= cp[3];
+ *r /= 255.0;
+
+ *g= cp[2];
+ *g /= 255.0;
+
+ *b= cp[1];
+ *b /= 255.0;
+
+ *a= cp[0];
+ *a /= 255.0;
+}
+
+static void write_mesh_vrml(FILE *fp, Mesh *me)
+{
+ Material *ma;
+ MVert *mvert;
+ MFace *mface;
+ TFace *tface;
+ Image *ima;
+ int a, b, totcol;
+ char str[32];
+
+ replace_chars(str, me->id.name+2);
+
+ fprintf(fp, "\tDEF %s\n", str);
+ fprintf(fp, "\tSeparator {\n");
+
+ if(me->tface) {
+ ima= ((TFace *)me->tface)->tpage;
+ if(ima) {
+ fprintf(fp, "\t\tTexture2 {\n");
+ fprintf(fp, "\t\t\tfilename %s\n", ima->name);
+ fprintf(fp, "\t\t\twrapS REPEAT \n");
+ fprintf(fp, "\t\t\twrapT REPEAT \n");
+ fprintf(fp, "\t\t}\n");
+ }
+ tface_to_mcol(me);
+ }
+
+ if(me->mcol) {
+ unsigned int *mcol, *mcolmain;
+ float r, g, b, cola;
+
+ fprintf(fp, "\t\tMaterial {\n");
+ fprintf(fp, "\t\t\tdiffuseColor [\n");
+
+ a= me->totvert;
+ mcol= mcolmain= mcol_to_vcol(me);
+ if(mcol) {
+ while(a--) {
+ mcol_to_rgba(*mcol, &r, &g, &b, &cola);
+ fprintf(fp, "\t\t\t\t %f %f %f,\n", r, g, b);
+ mcol++;
+ }
+ MEM_freeN(mcolmain);
+ }
+ fprintf(fp, "\t\t\t]\n");
+ fprintf(fp, "\t\t}\n");
+
+ fprintf(fp, "\t\tMaterialBinding { value PER_VERTEX_INDEXED }\n");
+ }
+
+
+ fprintf(fp, "\t\tCoordinate3 {\n");
+ fprintf(fp, "\t\t\tpoint [\n");
+
+ a= me->totvert;
+ mvert= me->mvert;
+ while(a--) {
+ fprintf(fp, "\t\t\t\t %f %f %f,\n", mvert->co[0], mvert->co[1], mvert->co[2]);
+ mvert++;
+ }
+ fprintf(fp, "\t\t\t]\n");
+ fprintf(fp, "\t\t}\n");
+
+
+ totcol= me->totcol;
+ if(totcol==0) totcol= 1;
+
+ for(b=0; b<totcol; b++) {
+
+ if(me->mcol==0) {
+ if(me->mat) {
+ ma= me->mat[b];
+ if(ma) {
+ replace_chars(str, ma->id.name+2);
+
+ fprintf(fp, "\t\tUSE %s\n\n", str);
+ }
+ }
+ }
+
+ if(me->tface) {
+ fprintf(fp, "\t\tTextureCoordinate2 {\n");
+ fprintf(fp, "\t\t\tpoint [\n");
+
+ a= me->totface;
+ mface= me->mface;
+ tface= me->tface;
+ while(a--) {
+ if(mface->mat_nr==b) {
+ fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[0][0], tface->uv[0][1]);
+ fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[3][0], tface->uv[3][1]);
+ if(mface->v3) fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[2][0], tface->uv[2][1]);
+ if(mface->v4) fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[1][0], tface->uv[1][1]);
+ }
+ mface++;
+ tface++;
+ }
+ fprintf(fp, "\t\t\t]\n");
+ fprintf(fp, "\t\t}\n");
+ }
+
+ fprintf(fp, "\t\tIndexedFaceSet {\n");
+ fprintf(fp, "\t\t\tcoordIndex [\n");
+
+ a= me->totface;
+ mface= me->mface;
+ while(a--) {
+ if(mface->mat_nr==b) {
+ if(mface->v4) fprintf(fp, "\t\t\t\t %d, %d, %d, %d, -1,\n", mface->v1, mface->v2, mface->v3, mface->v4);
+ else if(mface->v3) fprintf(fp, "\t\t\t\t %d, %d, %d, -1,\n", mface->v1, mface->v2, mface->v3);
+ }
+ mface++;
+ }
+ fprintf(fp, "\t\t\t]\n");
+ fprintf(fp, "\t\t}\n");
+
+ }
+
+ fprintf(fp, "\t}\n");
+
+ if(me->tface) {
+ MEM_freeN(me->mcol);
+ me->mcol= 0;
+ }
+
+}
+
+static void write_camera_vrml(FILE *fp, Object *ob)
+{
+ Camera *cam;
+
+ if(ob==0) return;
+ Mat4Invert(ob->imat, ob->obmat);
+
+ fprintf(fp, "\tMatrixTransform {\n");
+
+ fprintf(fp, "\tmatrix \n");
+
+ fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[0][0], ob->imat[0][1], ob->imat[0][2], ob->imat[0][3]);
+ fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[1][0], ob->imat[1][1], ob->imat[1][2], ob->imat[1][3]);
+ fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[2][0], ob->imat[2][1], ob->imat[2][2], ob->imat[2][3]);
+ fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[3][0], ob->imat[3][1], ob->imat[3][2], ob->imat[3][3]);
+
+ fprintf(fp, "\t}\n");
+
+ cam= ob->data;
+
+ fprintf(fp, "\tPerspectiveCamera {\n");
+ fprintf(fp, "\t\tfocalDistance %f\n", cam->lens/10.0);
+
+ fprintf(fp, "\t}\n");
+
+}
+
+static void write_object_vrml(FILE *fp, Object *ob)
+{
+ ID *id;
+ char str[32];
+
+ fprintf(fp, "\tSeparator {\n");
+ fprintf(fp, "\t\tMatrixTransform {\n");
+
+ fprintf(fp, "\t\tmatrix \n");
+
+ fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[0][0], ob->obmat[0][1], ob->obmat[0][2], ob->obmat[0][3]);
+ fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[1][0], ob->obmat[1][1], ob->obmat[1][2], ob->obmat[1][3]);
+ fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[2][0], ob->obmat[2][1], ob->obmat[2][2], ob->obmat[2][3]);
+ fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[3][0], ob->obmat[3][1], ob->obmat[3][2], ob->obmat[3][3]);
+
+ fprintf(fp, "\t\t}\n");
+
+ id= ob->data;
+
+ replace_chars(str, id->name+2);
+
+ fprintf(fp, "\t\tUSE %s\n", str);
+ fprintf(fp, "\t}\n");
+}
+
+
+void write_vrml(char *str)
+{
+ Mesh *me;
+ Material *ma;
+ Base *base;
+ FILE *fp;
+
+ if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
+ if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
+ if(BLI_testextensie(str,".wrl")==0) strcat(str, ".wrl");
+
+ if(saveover(str)==0) return;
+
+ fp= fopen(str, "w");
+
+ if(fp==NULL) {
+ error("Can't write file");
+ return;
+ }
+ strcpy(videosc_dir, str);
+
+ waitcursor(1);
+
+ /* FIRST: write all the datablocks */
+
+ fprintf(fp, "#VRML V1.0 ascii\n\n# Blender V2.0\n\n# 'Switch' is used as a hack, to ensure it is not part of the drawing\n\n");
+ fprintf(fp, "Separator {\n");
+ fprintf(fp, "Switch {\n");
+
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->id.us) {
+ write_material_vrml(fp, ma);
+ }
+ ma= ma->id.next;
+ }
+
+ me= G.main->mesh.first;
+ while(me) {
+ if(me->id.us) {
+ write_mesh_vrml(fp, me);
+ }
+ me= me->id.next;
+ }
+
+ /* THEN:Hidden Objects */
+ fprintf(fp, "\n\t# Hidden Objects, in invisible layers\n\n");
+ base= G.scene->base.first;
+ while(base) {
+ if(base->object->type== OB_MESH) {
+ if( (base->lay & G.scene->lay)==0 ) {
+ write_object_vrml(fp, base->object);
+ }
+ }
+ base= base->next;
+ }
+
+ fprintf(fp, "}\n");
+ fprintf(fp, "\n# Visible Objects\n\n");
+ fprintf(fp, "Separator {\n");
+
+ /* The camera */
+
+ write_camera_vrml(fp, G.scene->camera);
+
+ /* THEN:The Objects */
+
+ base= G.scene->base.first;
+ while(base) {
+ if(base->object->type== OB_MESH) {
+ if(base->lay & G.scene->lay) {
+ write_object_vrml(fp, base->object);
+ }
+ }
+ base= base->next;
+ }
+
+ fprintf(fp, "}\n");
+ fprintf(fp, "}\n");
+
+ fclose(fp);
+
+ waitcursor(0);
+}
+
+
+/* ******************************* WRITE DXF ***************************** */
+
+#define write_group(id,data) fprintf(fp, "%d\n%s\n", id, data)
+
+/* A completely wacky function to try and make good
+indexed (AutoCAD index) values out of straight rgb
+ones... crazy */
+
+static int rgb_to_dxf_col (float rf, float gf, float bf)
+{
+ int r= (int) (rf*255.0f);
+ int g= (int) (gf*255.0f);
+ int b= (int) (bf*255.0f);
+ float h,s,v;
+ int ret;
+
+ /* Grayscale value */
+ if (((int)r/10)==((int)g/10) && ((int)g/10)==((int)b/10)) ret= 250+((int)r/51);
+ /* A nice chroma value */
+ else {
+ rgb_to_hsv (rf,gf,bf,&h,&s,&v);
+
+ ret= (int) (10.0f + (h*239.0f));
+ CLAMP(ret,10,249);
+
+ /* If its whitish make the index odd */
+ if (s<.5 || v>.5) if(ret%2) ret++;
+ }
+
+ return ret;
+}
+
+/* And its completely wacky complement */
+
+static void dxf_col_to_rgb (int cid, float *rf, float *gf, float *bf)
+{
+ float h, s, v;
+
+ /* Grayscale values */
+ if (cid>=250 && cid <= 255) {
+ *rf= *gf= *bf= (float) ((cid-250)*51)/255;
+ CLAMP(*rf, 0.0, 1.0);
+ CLAMP(*gf, 0.0, 1.0);
+ CLAMP(*bf, 0.0, 1.0);
+
+ /* Pure values */
+ } else if (cid<10) {
+ switch (cid) {
+ case 1:
+ *rf=1.0;
+ *gf=0.0;
+ *bf=0.0;
+ break;
+ case 2:
+ *rf=1.0;
+ *gf=1.0;
+ *bf=0.0;
+ break;
+ case 3:
+ *gf=1.0;
+ *rf=0.0;
+ *bf=0.0;
+ break;
+ case 4:
+ *rf=0.0;
+ *gf=1.0;
+ *bf=1.0;
+ break;
+ case 5:
+ *rf=0.0;
+ *gf=0.0;
+ *bf=1.0;
+ break;
+ case 6:
+ *rf=1.0;
+ *gf=0.0;
+ *bf=1.0;
+ break;
+ case 7:
+ default:
+ *rf= *gf= *bf= 1.0;
+ break;
+ }
+ } else {
+ /* Get chroma values */
+
+ h= (float) (cid-10)/239;
+ CLAMP(h, 0.0, 1.0);
+
+ /* If its odd make it a bit whitish */
+ if (cid%2) { s=.75; v= 0.25;
+ } else { s= 0.25; v= 0.75;}
+
+ hsv_to_rgb (h, s, v, rf, gf, bf);
+ }
+}
+
+static void write_mesh_dxf(FILE *fp, Mesh *me)
+{
+ Material *ma;
+ MVert *mvert;
+ MFace *mface;
+ int a;
+ char str[32];
+
+ replace_chars(str, me->id.name+2);
+
+ write_group(0, "BLOCK");
+
+ write_group(2, str); /* The name */
+
+ write_group(8, "Meshes"); /* DXF Layer */
+ write_group(70, "64"); /* DXF block flags */
+
+ write_group(10, "0.0"); /* X of base */
+ write_group(20, "0.0"); /* Y of base */
+ write_group(30, "0.0"); /* Z of base */
+
+ write_group(3, str); /* The name (again) */
+
+ write_group(0, "POLYLINE"); /* Start the mesh */
+ write_group(66, "1"); /* Vertices follow flag */
+ write_group(8,"Meshes"); /* DXF Layer */
+
+ if (me->totcol) {
+ ma= me->mat[0];
+ if(ma) {
+ sprintf(str,"%d",rgb_to_dxf_col(ma->r,ma->g,ma->b));
+ write_group(62, str); /* Color index */
+ }
+ }
+
+ write_group(70, "64"); /* Polymesh mesh flag */
+
+ fprintf(fp, "71\n%d\n", me->totvert); /* Total vertices */
+ fprintf(fp, "72\n%d\n", me->totface); /* Total faces */
+
+ /* Write the vertices */
+ a= me->totvert;
+ mvert= me->mvert;
+ while(a--) {
+ write_group(0, "VERTEX"); /* Start a new vertex */
+ write_group(8, "Meshes"); /* DXF Layer */
+ fprintf (fp, "10\n%f\n", mvert->co[0]); /* X cord */
+ fprintf (fp, "20\n%f\n", mvert->co[1]); /* Y cord */
+ fprintf (fp, "30\n%f\n", mvert->co[2]); /* Z cord */
+ write_group(70, "192"); /* Polymesh vertex flag */
+
+ mvert++;
+ }
+
+ /* Write the face entries */
+ a= me->totface;
+ mface= me->mface;
+ while(a--) {
+ if (mface->v4 || mface->v3) {
+ write_group(0, "VERTEX"); /* Start a new face */
+ write_group(8, "Meshes");
+
+ /* Write a face color */
+ if (me->totcol) {
+ ma= me->mat[mface->mat_nr];
+ if(ma) {
+ sprintf(str,"%d",rgb_to_dxf_col(ma->r,ma->g,ma->b));
+ write_group(62, str); /* Color index */
+ }
+ }
+ else write_group(62, "254"); /* Color Index */
+
+ /* Not sure what this really corresponds too */
+ write_group(10, "0.0"); /* X of base */
+ write_group(20, "0.0"); /* Y of base */
+ write_group(30, "0.0"); /* Z of base */
+
+ write_group(70, "128"); /* Polymesh face flag */
+
+ if(mface->v4) {
+ fprintf (fp, "71\n%d\n", mface->v1+1);
+ fprintf (fp, "72\n%d\n", mface->v2+1);
+ fprintf (fp, "73\n%d\n", mface->v3+1);
+ fprintf (fp, "74\n%d\n", mface->v4+1);
+ } else if(mface->v3) {
+ fprintf (fp, "71\n%d\n", mface->v1+1);
+ fprintf (fp, "72\n%d\n", mface->v2+1);
+ fprintf (fp, "73\n%d\n", mface->v3+1);
+ }
+ }
+ mface++;
+ }
+
+ write_group(0, "SEQEND");
+
+ write_group(0, "ENDBLK");
+}
+
+static void write_object_dxf(FILE *fp, Object *ob, int layer)
+{
+ ID *id;
+ char str[32];
+
+ id= ob->data;
+
+ write_group(0, "INSERT"); /* Start an insert group */
+
+ sprintf(str, "%d", layer);
+ write_group(8, str);
+
+ replace_chars(str, id->name+2);
+ write_group(2, str);
+
+ fprintf (fp, "10\n%f\n", ob->loc[0]); /* X of base */
+ fprintf (fp, "20\n%f\n", ob->loc[1]); /* Y of base */
+ fprintf (fp, "30\n%f\n", ob->loc[2]); /* Z of base */
+
+ fprintf (fp, "41\n%f\n", ob->size[0]); /* X scale */
+ fprintf (fp, "42\n%f\n", ob->size[1]); /* Y scale */
+ fprintf (fp, "43\n%f\n", ob->size[2]); /* Z scale */
+
+ fprintf (fp, "50\n%f\n", (float) ob->rot[2]*180/M_PI); /* Can only write the Z rot */
+}
+
+void write_dxf(char *str)
+{
+ Mesh *me;
+ Base *base;
+ FILE *fp;
+
+ if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
+ if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
+ if(BLI_testextensie(str,".dxf")==0) strcat(str, ".dxf");
+
+ if (BLI_exists(str))
+ if(saveover(str)==0)
+ return;
+
+ fp= fopen(str, "w");
+
+ if(fp==NULL) {
+ error("Can't write file");
+ return;
+ }
+ strcpy(videosc_dir, str);
+
+ waitcursor(1);
+
+ /* The header part of the DXF */
+
+ write_group(0, "SECTION");
+ write_group(2, "HEADER");
+ write_group(0, "ENDSEC");
+
+ /* The blocks part of the DXF */
+
+ write_group(0, "SECTION");
+ write_group(2, "BLOCKS");
+
+ /* Write all the meshes */
+ me= G.main->mesh.first;
+ while(me) {
+ if(me->id.us) {
+ write_mesh_dxf(fp, me);
+ }
+ me= me->id.next;
+ }
+
+ write_group(0, "ENDSEC");
+
+ /* The entities part of the DXF */
+
+ write_group(0, "SECTION");
+ write_group(2, "ENTITIES");
+
+ /* Write all the mesh objects */
+ base= G.scene->base.first;
+ while(base) {
+ if(base->object->type== OB_MESH) {
+ write_object_dxf(fp, base->object, base->lay);
+ }
+ base= base->next;
+ }
+
+ write_group(0, "ENDSEC");
+
+ /* Thats all */
+
+ write_group(0, "EOF");
+ fclose(fp);
+
+ waitcursor(0);
+}
+
+
+static int dxf_line;
+static FILE *dxf_fp;
+
+/* exotic.c(2863) : note C6311: c:/Program Files/Microsoft Visual
+ * Studio/VC98/include\ctype.h(268) : see previous definition of
+ * 'iswspace' */
+#define ton_iswspace(c) (c==' '||c=='\n'||c=='\t')
+
+static void clean_wspace (char *str)
+{
+ char *from, *to;
+ char t;
+
+ from= str;
+ to=str;
+
+ while (*from!=0) {
+ t= *from;
+ *to= t;
+
+ if(!ton_iswspace(*from)) to++;
+ from++;
+ }
+ *to=0;
+}
+
+static int all_wspace(char *str)
+{
+ while(*str != 0) {
+ if (!ton_iswspace(*str)) return 0;
+ str++;
+ }
+
+ return 1;
+}
+
+static int all_digits(char *str)
+{
+ while(*str != 0) {
+ if (!isdigit(*str)) return 0;
+ str++;
+ }
+
+ return 1;
+}
+
+static int dxf_get_layer_col(char *layer)
+{
+ return 1;
+}
+
+static int dxf_get_layer_num(char *layer)
+{
+ int ret = 1;
+
+ if (all_digits(layer) && atoi(layer)<(1<<20)) ret= atoi(layer);
+ if (ret == 0) ret = 1;
+
+ return ret;
+}
+
+static void dos_clean(char *str)
+{
+ while (*str) {
+ if (*str == 0x0d) {
+ *str='\n';
+ *(++str)= 0;
+ break;
+ }
+ str++;
+ }
+}
+
+static int read_groupf(char *str)
+{
+ short c;
+ int ret=-1;
+ char tmp[256];
+
+ strcpy(str, " ");
+
+ while ((c=getc(dxf_fp)) && ton_iswspace(c));
+ ungetc(c, dxf_fp);
+ if (c==EOF) return -1;
+
+ fgets(tmp, 255, dxf_fp);
+
+ dos_clean(tmp);
+
+ if(sscanf(tmp, "%d\n", &ret)!=1) return -2;
+
+ fgets(tmp, 255, dxf_fp);
+
+ dos_clean(tmp);
+
+ if (!all_wspace(tmp)) {
+ if (sscanf(tmp, "%s\n", str)!=1) return -2;
+ }
+
+ clean_wspace(str);
+ dxf_line+=2;
+
+ return ret;
+}
+
+#define id_test(id) if(id<0) {char errmsg[128];fclose(dxf_fp); if(id==-1) sprintf(errmsg, "Error inputting dxf, near line %d", dxf_line); else if(id==-2) sprintf(errmsg, "Error reading dxf, near line %d", dxf_line);error(errmsg); return;}
+
+#define read_group(id,str) {id= read_groupf(str); id_test(id);}
+
+#define group_is(idtst,str) (id==idtst&&strcmp(val,str)==0)
+#define group_isnt(idtst,str) (id!=idtst||strcmp(val,str)!=0)
+#define id_check(idtst,str) if(group_isnt(idtst,str)) { fclose(dxf_fp); error("Error parsing dxf, near line %d", dxf_line); return;}
+
+static int id;
+static char val[256];
+
+static short error_exit=0;
+static short hasbumped=0;
+
+static int is_dxf(char *str)
+{
+ dxf_line=0;
+
+ dxf_fp= fopen(str, "r");
+ if (dxf_fp==NULL) return 0;
+
+ id= read_groupf(val);
+ if ((id==0 && strcmp(val, "SECTION")==0)||id==999) return 1;
+
+ fclose(dxf_fp);
+
+ return 0;
+}
+
+/* NOTES ON THE READER */
+/*
+ --
+ It turns out that most DXF writers like (LOVE) to
+ write meshes as a long string of 3DFACE entities.
+ This means the natural way to read a DXF file
+ (every entity corresponds to an object) is completely
+ unusable, reading in 10,000 faces each as an
+ object just doesn't cut it. Thus the 3DFACE
+ entry reader holds state, and only finalizes to
+ an object when a) the layer name changes, b) the
+ entry type changes, c) we are done reading.
+
+ PS... I decided to do the same thing with LINES,
+ apparently the same thing happens sometimes as
+ well.
+
+ PPS... I decided to do the same thing with everything.
+ Now it is all really nasty and should be rewritten.
+*/
+
+static void dxf_add_mat (Object *ob, Mesh *me, float color[3], char *layer)
+{
+ Material *ma;
+
+ if (!me) return;
+
+ if(ob) ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat");
+ if(ob) ob->totcol= 1;
+ if(ob) ob->actcol= 1;
+
+ me->totcol= 1;
+ me->mat= MEM_callocN(sizeof(void *)*1, "me->mat");
+
+ if (color[0]<0) {
+ if (strlen(layer)) dxf_col_to_rgb(dxf_get_layer_col(layer), &color[0], &color[1], &color[2]);
+ color[0]= color[1]= color[2]= 0.8f;
+ }
+
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->mtex[0]==0) {
+ if(color[0]==ma->r && color[1]==ma->g && color[2]==ma->b) {
+ me->mat[0]= ma;
+ ma->id.us++;
+ break;
+ }
+ }
+ ma= ma->id.next;
+ }
+ if(ma==0) {
+ ma= add_material("ext");
+ me->mat[0]= ma;
+ ma->r= color[0];
+ ma->g= color[1];
+ ma->b= color[2];
+ automatname(ma);
+ }
+}
+
+ /* General DXF vars */
+static float cent[3]={0.0, 0.0, 0.0};
+static char layname[32]="";
+static char entname[32]="";
+static float color[3]={-1.0, -1.0, -1.0};
+static float *vcenter;
+static float zerovec[3]= {0.0, 0.0, 0.0};
+
+#define reset_vars cent[0]= cent[1]= cent[2]=0.0; strcpy(layname, ""); color[0]= color[1]= color[2]= -1.0
+
+static void dxf_read_point(int noob) {
+ /* Blender vars */
+ Object *ob;
+ Mesh *me;
+ MVert *mvert;
+
+ reset_vars;
+
+ read_group(id, val);
+ while(id!=0) {
+ if (id==8) {
+ BLI_strncpy(layname, val, sizeof(layname));
+ } else if (id==10) {
+ cent[0]= (float) atof(val);
+ } else if (id==20) {
+ cent[1]= (float) atof(val);
+ } else if (id==30) {
+ cent[2]= (float) atof(val);
+ } else if (id==60) {
+ /* short invisible= atoi(val); */
+ } else if (id==62) {
+ int colorid= atoi(val);
+
+ CLAMP(colorid, 1, 255);
+ dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
+ }
+ read_group(id, val);
+ }
+
+ if (noob) {
+ ob= NULL;
+ me= add_mesh(); G.totmesh++;
+ ((ID *)me)->us=0;
+
+ if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname);
+ else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname);
+
+ vcenter= zerovec;
+ } else {
+ ob= add_object(OB_MESH);
+ if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname);
+ else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname);
+
+ if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
+ else ob->lay= G.scene->lay;
+
+ me= ob->data;
+
+ vcenter= ob->loc;
+ }
+ me->totvert= 1; /* Its a line dude */
+ me->totface= 0;
+
+ me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+ me->mface= NULL;
+
+ dxf_add_mat (ob, me, color, layname);
+
+ mvert= me->mvert;
+ mvert->co[0]= mvert->co[1]= mvert->co[2]= 0;
+
+ if (ob) VECCOPY(ob->loc, cent);
+
+ if (!noob) {
+ G.obedit= ob;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+ waitcursor(1); /* patch yah... */
+
+ G.obedit= 0;
+ }
+ tex_space_mesh(me);
+
+ hasbumped=1;
+}
+
+ /* Line state vars */
+static Object *linehold=NULL;
+static Mesh *linemhold=NULL;
+
+static char oldllay[32];
+static short lwasline=0; /* last was face 3d? */
+
+static void dxf_close_line(void)
+{
+ linemhold=NULL;
+ if (linehold==NULL) return;
+
+ G.obedit= linehold;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+ waitcursor(1); /* patch yah... */
+
+ G.obedit= 0;
+ tex_space_mesh(linehold->data);
+
+ linehold=NULL;
+}
+
+static void dxf_read_line(int noob) {
+ /* Entity specific vars */
+ float epoint[3]={0.0, 0.0, 0.0};
+ short vspace=0; /* Whether or not coords are relative */
+
+ /* Blender vars */
+ Object *ob;
+ Mesh *me;
+ MVert *mvert, *vtmp;
+ MFace *mface, *ftmp;
+
+ reset_vars;
+
+ read_group(id, val);
+ while(id!=0) {
+ if (id==8) {
+ BLI_strncpy(layname, val, sizeof(layname));
+ } else if (id==10) {
+ cent[0]= (float) atof(val);
+ } else if (id==20) {
+ cent[1]= (float) atof(val);
+ } else if (id==30) {
+ cent[2]= (float) atof(val);
+ } else if (id==11) {
+ epoint[0]= (float) atof(val);
+ } else if (id==21) {
+ epoint[1]= (float) atof(val);
+ } else if (id==31) {
+ epoint[2]= (float) atof(val);
+ } else if (id==60) {
+ /* short invisible= atoi(val); */
+ } else if (id==62) {
+ int colorid= atoi(val);
+
+ CLAMP(colorid, 1, 255);
+ dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
+ } else if (id==67) {
+ vspace= atoi(val);
+ }
+ read_group(id, val);
+ }
+
+ /* Check to see if we need to make a new object */
+
+ if(!lwasline || strcmp(layname, oldllay)!=0) dxf_close_line();
+ if(linemhold != NULL && linemhold->totvert>65000) dxf_close_line();
+
+ if (linemhold==NULL) {
+ if (noob) {
+ ob= NULL;
+ me= add_mesh(); G.totmesh++;
+ ((ID *)me)->us=0;
+
+ if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname);
+ else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname);
+
+ vcenter= zerovec;
+ } else {
+ ob= add_object(OB_MESH);
+ if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname);
+ else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname);
+
+ if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
+ else ob->lay= G.scene->lay;
+
+ me= ob->data;
+
+ vcenter= ob->loc;
+ }
+
+ me->totvert=0;
+ me->totface=0;
+ me->mvert=NULL;
+ me->mface=NULL;
+
+ strcpy(oldllay, layname);
+
+ if(ob) VECCOPY(ob->loc, cent);
+
+ dxf_add_mat (ob, me, color, layname);
+
+ linehold= ob;
+ linemhold= me;
+ } else {
+ ob= linehold;
+ me= linemhold;
+ }
+
+ me->totvert+= 2;
+ me->totface++;
+
+ vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+ ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface");
+
+ if(me->mvert) {
+ memcpy(vtmp, me->mvert, (me->totvert-2)*sizeof(MVert));
+ MEM_freeN(me->mvert);
+ }
+ me->mvert= vtmp;
+ vtmp=NULL;
+
+ if(me->mface) {
+ memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace));
+ MEM_freeN(me->mface);
+ }
+ me->mface= ftmp;
+ ftmp=NULL;
+
+ mvert= &me->mvert[(me->totvert-2)];
+ VecSubf(mvert->co, cent, vcenter);
+
+ mvert++;
+ if (vspace) { VECCOPY(mvert->co, epoint);
+ } else VecSubf(mvert->co, epoint, vcenter);
+
+ mface= &(((MFace*)me->mface)[me->totface-1]);
+ mface->v1= me->totvert-2;
+ mface->v2= me->totvert-1;
+
+ mface->edcode= 1;
+ mface->mat_nr= 0;
+
+ hasbumped=1;
+}
+
+ /* 2D Polyline state vars */
+static Object *p2dhold=NULL;
+static Mesh *p2dmhold=NULL;
+static char oldplay[32];
+static short lwasp2d=0;
+
+static void dxf_close_2dpoly(void)
+{
+ p2dmhold= NULL;
+ if (p2dhold==NULL) return;
+
+ G.obedit= p2dhold;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+ waitcursor(1); /* patch yah... */
+
+ G.obedit= 0;
+ tex_space_mesh(p2dhold->data);
+
+ p2dhold=NULL;
+}
+
+static void dxf_read_polyline(int noob) {
+ /* Entity specific vars */
+ short vspace=0; /* Whether or not coords are relative */
+ int flag=0;
+ int vflags=0;
+ int vids[4];
+ int nverts;
+
+ /* Blender vars */
+ Object *ob;
+ Mesh *me;
+ float vert[3];
+
+ MVert *mvert, *vtmp;
+ MFace *mface, *ftmp;
+
+ reset_vars;
+
+ read_group(id, val);
+ while(id!=0) {
+ if (id==8) {
+ BLI_strncpy(layname, val, sizeof(layname));
+ } else if (id==10) {
+ cent[0]= (float) atof(val);
+ } else if (id==20) {
+ cent[1]= (float) atof(val);
+ } else if (id==30) {
+ cent[2]= (float) atof(val);
+ } else if (id==60) {
+ /* short invisible= atoi(val); */
+ } else if (id==62) {
+ int colorid= atoi(val);
+
+ CLAMP(colorid, 1, 255);
+ dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
+ } else if (id==67) {
+ vspace= atoi(val);
+ } else if (id==70) {
+ flag= atoi(val);
+ }
+ read_group(id, val);
+ }
+
+ if (flag&1) {
+ if(!lwasp2d || strcmp(layname, oldplay)!=0) dxf_close_2dpoly();
+ if(p2dmhold != NULL && p2dmhold->totvert>65000) dxf_close_2dpoly();
+
+ if (p2dmhold==NULL) {
+ if (noob) {
+ ob= NULL;
+ me= add_mesh(); G.totmesh++;
+ ((ID *)me)->us=0;
+
+ if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname);
+ else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname);
+
+ vcenter= zerovec;
+ } else {
+ ob= add_object(OB_MESH);
+ if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname);
+ else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname);
+
+ if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
+ else ob->lay= G.scene->lay;
+
+ me= ob->data;
+
+ vcenter= ob->loc;
+ }
+ me->totvert=0;
+ me->totface=0;
+ me->mvert=NULL;
+ me->mface=NULL;
+
+ strcpy(oldplay, layname);
+
+ if(ob) VECCOPY(ob->loc, cent);
+
+ dxf_add_mat (ob, me, color, layname);
+
+ p2dhold= ob;
+ p2dmhold= me;
+ } else {
+ ob= p2dhold;
+ me= p2dmhold;
+ }
+
+ nverts=0;
+ while (group_is(0, "VERTEX")) {
+ read_group(id, val);
+ while(id!=0) {
+ if (id==10) {
+ vert[0]= (float) atof(val);
+ } else if (id==20) {
+ vert[1]= (float) atof(val);
+ } else if (id==30) {
+ vert[2]= (float) atof(val);
+ }
+ read_group(id, val);
+ }
+ nverts++;
+ me->totvert++;
+
+ vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+
+ if (me->mvert) {
+ memcpy (vtmp, me->mvert, (me->totvert-1)*sizeof(MVert));
+ MEM_freeN(me->mvert);
+ }
+ me->mvert= vtmp;
+ vtmp= NULL;
+
+ mvert= &me->mvert[me->totvert-1];
+
+ if (vspace) { VECCOPY(mvert->co, vert);
+ } else VecSubf(mvert->co, vert, vcenter);
+ }
+
+ me->totface++;
+ ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface");
+
+ if(me->mface) {
+ memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace));
+ MEM_freeN(me->mface);
+ }
+ me->mface= ftmp;
+ ftmp=NULL;
+
+ mface= &(((MFace*)me->mface)[me->totface-1]);
+
+ mface->v1= (me->totvert-nverts)+0;
+ mface->v2= (me->totvert-nverts)+1;
+ mface->v3= (me->totvert-nverts)+2;
+ if (nverts==4) mface->v4= (me->totvert-nverts)+3;
+
+ mface->edcode= 3;
+ mface->mat_nr= 0;
+
+ test_index_mface(mface, nverts);
+
+ lwasp2d=1;
+ } else if (flag&64) {
+ if (noob) {
+ ob= NULL;
+ me= add_mesh(); G.totmesh++;
+ ((ID *)me)->us=0;
+
+ if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname);
+ else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname);
+
+ vcenter= zerovec;
+ } else {
+ ob= add_object(OB_MESH);
+ if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname);
+ else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname);
+
+ if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
+ else ob->lay= G.scene->lay;
+
+ me= ob->data;
+
+ vcenter= ob->loc;
+ }
+ me->totvert=0;
+ me->totface=0;
+ me->mvert=NULL;
+ me->mface=NULL;
+
+ if(ob) VECCOPY(ob->loc, cent);
+
+ dxf_add_mat (ob, me, color, layname);
+
+ while (group_is(0, "VERTEX")) {
+ vflags= 0;
+ vids[0]= vids[1]= vids[2]= vids[3]= 0;
+
+ vflags=0;
+ read_group(id, val);
+ while(id!=0) {
+ if(id==8) {
+ ; /* Layer def, skip */
+ } else if (id==10) {
+ vert[0]= (float) atof(val);
+ } else if (id==20) {
+ vert[1]= (float) atof(val);
+ } else if (id==30) {
+ vert[2]= (float) atof(val);
+ } else if (id==70) {
+ vflags= atoi(val);
+ } else if (id==71) {
+ vids[0]= abs(atoi(val));
+ } else if (id==72) {
+ vids[1]= abs(atoi(val));
+ } else if (id==73) {
+ vids[2]= abs(atoi(val));
+ } else if (id==74) {
+ vids[3]= abs(atoi(val));
+ }
+ read_group(id, val);
+ }
+
+ if (vflags & 128 && vflags & 64) {
+ me->totvert++;
+
+ /* If we are nearing the limit scan to the next entry */
+ if(me->totvert > 65000) while(group_isnt(0, "SEQEND")) read_group(id, val);
+
+ vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+
+ if(me->mvert) {
+ memcpy(vtmp, me->mvert, (me->totvert-1)*sizeof(MVert));
+ MEM_freeN(me->mvert);
+ }
+ me->mvert= vtmp;
+ vtmp=NULL;
+
+ mvert= &me->mvert[(me->totvert-1)];
+
+ if (vspace) { VECCOPY(mvert->co, vert);
+ } else VecSubf(mvert->co, vert, vcenter);
+
+ } else if (vflags & 128) {
+ if(vids[2]==0) {
+ error("(PL) Error parsing dxf, not enough vertices near line %d", dxf_line);
+
+ error_exit=1;
+ fclose(dxf_fp);
+ return;
+ }
+
+ me->totface++;
+
+ ftmp= MEM_callocN(me->totface*sizeof(MFace), "mfaces");
+
+ if(me->mface) {
+ memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace));
+ MEM_freeN(me->mface);
+ }
+ me->mface= ftmp;
+ ftmp=NULL;
+
+ mface= &(((MFace*)me->mface)[me->totface-1]);
+ mface->v1= vids[0]-1;
+ mface->v2= vids[1]-1;
+ mface->v3= vids[2]-1;
+
+ if(vids[3])
+ mface->v4= vids[3]-1;
+
+ mface->edcode= 3;
+ mface->mat_nr= 0;
+
+ if(vids[3])
+ test_index_mface(mface, 4);
+ else
+ test_index_mface(mface, 3);
+ } else {
+ error("Error parsing dxf, unknown polyline information near %d", dxf_line);
+
+ error_exit=1;
+ fclose(dxf_fp);
+ return;
+ }
+
+ }
+
+ if (!noob) {
+ G.obedit= ob;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+ waitcursor(1); /* patch yah... */
+ G.obedit= 0;
+ }
+ tex_space_mesh(me);
+ }
+}
+
+ /* 3D Face state vars */
+static Object *f3dhold=NULL;
+static Mesh *f3dmhold=NULL;
+static char oldflay[32];
+static short lwasf3d=0; /* last was face 3d? */
+
+static void dxf_close_3dface(void)
+{
+ f3dmhold= NULL;
+ if (f3dhold==NULL) return;
+
+ G.obedit= f3dhold;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+ waitcursor(1); /* patch yah... */
+ G.obedit= 0;
+ tex_space_mesh(f3dhold->data);
+
+ f3dhold=NULL;
+}
+
+static void dxf_read_3dface(int noob)
+{
+ /* Entity specific vars */
+ float vert2[3]={0.0, 0.0, 0.0};
+ float vert3[3]={0.0, 0.0, 0.0};
+ float vert4[3]={0.0, 0.0, 0.0};
+ short vspace=0;
+
+ int nverts=0;
+
+ /* Blender vars */
+ Object *ob;
+ Mesh *me;
+ MVert *mvert, *vtmp;
+ MFace *mface, *ftmp;
+
+ reset_vars;
+
+ read_group(id, val);
+ while(id!=0) {
+ if (id==8) {
+ BLI_strncpy(layname, val, sizeof(layname));
+
+ /* First vert/origin */
+ } else if (id==10) {
+ cent[0]= (float) atof(val);
+ if (nverts<1)nverts++;
+ } else if (id==20) {
+ cent[1]= (float) atof(val);
+ if (nverts<1)nverts++;
+ } else if (id==30) {
+ cent[2]= (float) atof(val);
+ if (nverts<1)nverts++;
+
+ /* Second vert */
+ } else if (id==11) {
+ vert2[0]= (float) atof(val);
+ if (nverts<2)nverts++;
+ } else if (id==21) {
+ vert2[1]= (float) atof(val);
+ if (nverts<2)nverts++;
+ } else if (id==31) {
+ vert2[2]= (float) atof(val);
+ if (nverts<2)nverts++;
+
+ /* Third vert */
+ } else if (id==12) {
+ vert3[0]= (float) atof(val);
+ if (nverts<3)nverts++;
+ } else if (id==22) {
+ vert3[1]= (float) atof(val);
+ if (nverts<3)nverts++;
+ } else if (id==32) {
+ vert3[2]= (float) atof(val);
+ if (nverts<3)nverts++;
+
+ /* Fourth vert */
+ } else if (id==13) {
+ vert4[0]= (float) atof(val);
+ if (nverts<4)nverts++;
+ } else if (id==23) {
+ vert4[1]= (float) atof(val);
+ if (nverts<4)nverts++;
+ } else if (id==33) {
+ vert4[2]= (float) atof(val);
+ if (nverts<4)nverts++;
+
+ /* Other */
+ } else if (id==60) {
+ /* short invisible= atoi(val); */
+ } else if (id==62) {
+ int colorid= atoi(val);
+
+ CLAMP(colorid, 1, 255);
+ dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
+ } else if (id==67) {
+ vspace= atoi(val);
+ }
+ read_group(id, val);
+ }
+
+ /* Check to see if we need to make a new object */
+
+ if(!lwasf3d || strcmp(layname, oldflay)!=0) dxf_close_3dface();
+ if(f3dmhold != NULL && f3dmhold->totvert>65000) dxf_close_3dface();
+
+ if(nverts<3) {
+ error("(3DF) Error parsing dxf, not enough vertices near line %d", dxf_line);
+
+ error_exit=1;
+ fclose(dxf_fp);
+ return;
+ }
+
+ if (f3dmhold==NULL) {
+ if (noob) {
+ ob= NULL;
+ me= add_mesh(); G.totmesh++;
+ ((ID *)me)->us=0;
+
+ if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname);
+ else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname);
+
+ vcenter= zerovec;
+ } else {
+ ob= add_object(OB_MESH);
+ if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname);
+ else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname);
+
+ if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
+ else ob->lay= G.scene->lay;
+
+ me= ob->data;
+
+ vcenter= ob->loc;
+ }
+ me->totvert=0;
+ me->totface=0;
+ me->mvert=NULL;
+ me->mface=NULL;
+
+ strcpy(oldflay, layname);
+
+ if(ob) VECCOPY(ob->loc, cent);
+
+ dxf_add_mat (ob, me, color, layname);
+
+ f3dhold= ob;
+ f3dmhold= me;
+ } else {
+ ob= f3dhold;
+ me= f3dmhold;
+ }
+
+ me->totvert+= nverts;
+ me->totface++;
+
+ vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+ ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface");
+
+ if(me->mvert) {
+ memcpy(vtmp, me->mvert, (me->totvert-nverts)*sizeof(MVert));
+ MEM_freeN(me->mvert);
+ }
+ me->mvert= vtmp;
+ vtmp=NULL;
+
+ if(me->mface) {
+ memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace));
+ MEM_freeN(me->mface);
+ }
+ me->mface= ftmp;
+ ftmp=NULL;
+
+ mvert= &me->mvert[(me->totvert-nverts)];
+ VecSubf(mvert->co, cent, vcenter);
+
+ mvert++;
+ if (vspace) { VECCOPY(mvert->co, vert2);
+ } else VecSubf(mvert->co, vert2, vcenter);
+
+ mvert++;
+ if (vspace) { VECCOPY(mvert->co, vert3);
+ } else VecSubf(mvert->co, vert3, vcenter);
+
+ if (nverts==4) {
+ mvert++;
+ if (vspace) { VECCOPY(mvert->co, vert4);
+ } else VecSubf(mvert->co, vert4, vcenter);
+ }
+
+ mface= &(((MFace*)me->mface)[me->totface-1]);
+ mface->v1= (me->totvert-nverts)+0;
+ mface->v2= (me->totvert-nverts)+1;
+ mface->v3= (me->totvert-nverts)+2;
+
+ if (nverts==4)
+ mface->v4= (me->totvert-nverts)+3;
+
+ mface->edcode= 3;
+ mface->mat_nr= 0;
+
+ test_index_mface(mface, nverts);
+
+ hasbumped=1;
+}
+
+static void dxf_read(char *filename)
+{
+ dxf_line=0;
+
+ dxf_fp= fopen(filename, "r");
+ if (dxf_fp==NULL) return;
+
+ while (1) {
+ read_group(id, val);
+ if (group_is(0, "EOF")) break;
+
+ if (id==999) continue;
+ id_check(0, "SECTION");
+
+ read_group(id, val);
+ if (group_is(2, "HEADER")) {
+ } else if (group_is(2, "TABLES")) {
+ } else if (group_is(2, "OBJECTS")) {
+ } else if (group_is(2, "CLASSES")) {
+ } else if (group_is(2, "BLOCKS")) {
+ while(1) {
+ read_group(id, val);
+ if (group_is(0, "BLOCK")) {
+ while(group_isnt(0, "ENDBLK")) {
+ read_group(id, val);
+ if(id==2) {
+ BLI_strncpy(entname, val, sizeof(entname));
+ } else if (id==3) {
+ /* Now the object def should follow */
+ if(strlen(entname)==0) {
+ error("Error parsing dxf, no mesh name near %d", dxf_line);
+ fclose(dxf_fp);
+ return;
+ }
+
+ /* Now the object def should follow */
+ while(group_isnt(0, "ENDBLK")) {
+ read_group(id, val);
+ if(group_is(0, "POLYLINE")) {
+ dxf_read_polyline(1);
+ if(error_exit) return;
+ lwasf3d=0;
+ lwasline=0;
+
+ while(group_isnt(0, "SEQEND")) read_group(id, val);
+ } else if(group_is(0, "ATTRIB")) {
+ while(group_isnt(0, "SEQEND")) read_group(id, val);
+ lwasf3d=0;
+ lwasp2d=0;
+ lwasline=0;
+ } else if(group_is(0, "POINT")) {
+ dxf_read_point(1);
+ if(error_exit) return;
+ lwasf3d=0;
+ lwasp2d=0;
+ lwasline=0;
+ } else if(group_is(0, "LINE")) {
+ dxf_read_line(1);
+ if(error_exit) return;
+ lwasline=1;
+ lwasp2d=0;
+ lwasf3d=0;
+ } else if(group_is(0, "3DFACE")) {
+ dxf_read_3dface(1);
+ if(error_exit) return;
+ lwasf3d=1;
+ lwasp2d=0;
+ lwasline=0;
+ } else if (group_is(0, "ENDBLK")) {
+ break;
+ }
+ }
+ } else if (group_is(0, "ENDBLK")) {
+ break;
+ }
+ }
+ while(id!=0) read_group(id, val);
+ } else if(group_is(0, "ENDSEC")) {
+ break;
+ }
+ }
+ } else if (group_is(2, "ENTITIES")) {
+ while(group_isnt(0, "ENDSEC")) {
+ char obname[32]="";
+ char layname[32]="";
+ float cent[3]={0.0, 0.0, 0.0};
+ float obsize[3]={1.0, 1.0, 1.0};
+ float obrot[3]={0.0, 0.0, 0.0};
+ int i;
+
+ if(!hasbumped) read_group(id, val);
+ hasbumped=0;
+ if (group_is(0, "INSERT")) {
+ Base *base;
+ Object *ob;
+ void *obdata;
+
+ read_group(id, val);
+ while(id!=0) {
+ if(id==2) {
+ BLI_strncpy(obname, val, sizeof(obname));
+ } else if (id==8) {
+ BLI_strncpy(layname, val, sizeof(layname));
+ } else if (id==10) {
+ cent[0]= (float) atof(val);
+ } else if (id==20) {
+ cent[1]= (float) atof(val);
+ } else if (id==30) {
+ cent[2]= (float) atof(val);
+ } else if (id==41) {
+ obsize[0]= (float) atof(val);
+ } else if (id==42) {
+ obsize[1]= (float) atof(val);
+ } else if (id==43) {
+ obsize[2]= (float) atof(val);
+ } else if (id==50) {
+ obrot[2]= (float) (atof(val)*M_PI/180.0);
+ } else if (id==60) {
+ /* short invisible= atoi(val); */
+ }
+
+ read_group(id, val);
+ }
+
+ if(strlen(obname)==0) {
+ error("Error parsing dxf, no object name near %d", dxf_line);
+ fclose(dxf_fp);
+ return;
+ }
+
+ obdata= find_id("ME", obname);
+
+ if (obdata) {
+ ob= alloc_libblock(&G.main->object, ID_OB, obname);
+
+ ob->type= OB_MESH;
+
+ ob->dt= OB_SHADED;
+ if(U.flag & MAT_ON_OB) ob->colbits= -1;
+
+ ob->trackflag= OB_POSY;
+ ob->upflag= OB_POSZ;
+
+ ob->ipoflag = OB_OFFS_OB+OB_OFFS_PARENT;
+
+ ob->dupon= 1; ob->dupoff= 0;
+ ob->dupsta= 1; ob->dupend= 100;
+
+ G.totobj++;
+
+ ob->data= obdata;
+ ((ID*)ob->data)->us++;
+
+ VECCOPY(ob->loc, cent);
+ VECCOPY(ob->size, obsize);
+ VECCOPY(ob->rot, obrot);
+
+ ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat");
+ ob->totcol= (unsigned char) ((Mesh*)ob->data)->totcol;
+ ob->actcol= 1;
+
+ for (i=0; i<ob->totcol; i++) ob->mat[i]= ((Mesh*)ob->data)->mat[i];
+
+ if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
+ else ob->lay= G.scene->lay;
+
+ /* aan de scene hangen */
+ base= MEM_callocN( sizeof(Base), "add_base");
+ BLI_addhead(&G.scene->base, base);
+
+ base->lay= ob->lay;
+
+ base->object= ob;
+
+ G.obedit= ob;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+ waitcursor(1); /* patch yah... */
+ G.obedit= 0;
+ tex_space_mesh(ob->data);
+ }
+
+ hasbumped=1;
+
+ lwasf3d=0;
+ lwasp2d=0;
+ lwasline=0;
+ } else if(group_is(0, "POLYLINE")) {
+ dxf_read_polyline(0);
+ if(error_exit) return;
+ lwasf3d=0;
+ lwasline=0;
+
+ while(group_isnt(0, "SEQEND")) read_group(id, val);
+ } else if(group_is(0, "ATTRIB")) {
+ while(group_isnt(0, "SEQEND")) read_group(id, val);
+ lwasf3d=0;
+ lwasp2d=0;
+ lwasline=0;
+ } else if(group_is(0, "POINT")) {
+ dxf_read_point(0);
+ if(error_exit) return;
+ lwasf3d=0;
+ lwasp2d=0;
+ lwasline=0;
+ } else if(group_is(0, "LINE")) {
+ dxf_read_line(0);
+ if(error_exit) return;
+ lwasline=1;
+ lwasp2d=0;
+ lwasf3d=0;
+ } else if(group_is(0, "3DFACE")) {
+ dxf_read_3dface(0);
+ if(error_exit) return;
+ lwasline=0;
+ lwasp2d=0;
+ lwasf3d=1;
+ } else if(group_is(0, "ENDSEC")) {
+ break;
+ }
+ }
+ }
+
+ while(group_isnt(0, "ENDSEC")) read_group(id, val);
+ }
+ id_check(0, "EOF");
+
+ fclose (dxf_fp);
+
+ /* Close any remaining state held stuff */
+ dxf_close_3dface();
+ dxf_close_2dpoly();
+ dxf_close_line();
+}
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
new file mode 100644
index 00000000000..4f6b6c4b0c2
--- /dev/null
+++ b/source/blender/blenkernel/intern/font.c
@@ -0,0 +1,656 @@
+
+/* font.c MIXED MODEL
+ *
+ * maart 95
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_vfontdata.h"
+
+#include "DNA_packedFile_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_bad_level_calls.h"
+
+#include "BKE_packedFile.h"
+
+#include "BKE_library.h"
+#include "BKE_font.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_screen.h"
+#include "BKE_anim.h"
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+
+/* Nieuwe opzet voor vectorfont:
+ *
+ * geen PDrawfont meer, alles meteen naar Nurb en BezTriple
+ *
+ */
+
+struct chartrans {
+ float xof, yof;
+ float rot;
+ short linenr,charnr;
+};
+
+void free_vfont(struct VFont *vf)
+{
+ int i;
+
+ if (vf == 0) return;
+
+ if (vf->data) {
+ for (i = 0; i < MAX_VF_CHARS; i++){
+ while (vf->data->nurbsbase[i].first) {
+ Nurb *nu = vf->data->nurbsbase[i].first;
+ if (nu->bezt) MEM_freeN(nu->bezt);
+ BLI_freelinkN(&vf->data->nurbsbase[i], nu);
+ }
+ }
+
+ MEM_freeN(vf->data);
+ vf->data = NULL;
+ }
+
+ if (vf->packedfile) {
+ freePackedFile(vf->packedfile);
+ vf->packedfile = NULL;
+ }
+}
+
+static void *builtin_font_data= NULL;
+static int builtin_font_size= 0;
+
+void BKE_font_register_builtin(void *mem, int size)
+{
+ builtin_font_data= mem;
+ builtin_font_size= size;
+}
+
+static PackedFile *get_builtin_packedfile(void)
+{
+ if (!builtin_font_data) {
+ printf("Internal error, builtin font not loaded");
+
+ return NULL;
+ } else {
+ void *mem= MEM_mallocN(builtin_font_size, "vfd_builtin");
+
+ memcpy(mem, builtin_font_data, builtin_font_size);
+
+ return newPackedFileMemory(mem, builtin_font_size);
+ }
+}
+
+static VFontData *vfont_get_data(VFont *vfont)
+{
+ if (!vfont->data) {
+ PackedFile *pf;
+
+ if (BLI_streq(vfont->name, "<builtin>")) {
+ pf= get_builtin_packedfile();
+ } else {
+ if (vfont->packedfile) {
+ pf= vfont->packedfile;
+ } else {
+ pf= newPackedFile(vfont->name);
+ }
+ }
+
+ if (pf) {
+ vfont->data= BLI_vfontdata_from_psfont(pf);
+
+ if (pf != vfont->packedfile) {
+ freePackedFile(pf);
+ }
+ }
+ }
+
+ return vfont->data;
+}
+
+VFont *load_vfont(char *name)
+{
+ char filename[FILE_MAXFILE];
+ VFont *vfont= NULL;
+ PackedFile *pf;
+ int is_builtin;
+
+ if (BLI_streq(name, "<builtin>")) {
+ strcpy(filename, name);
+
+ pf= get_builtin_packedfile();
+ is_builtin= 1;
+ } else {
+ char dir[FILE_MAXDIR];
+
+ strcpy(dir, name);
+ BLI_splitdirstring(dir, filename);
+
+ pf= newPackedFile(name);
+ is_builtin= 0;
+ }
+
+ if (pf) {
+ VFontData *vfd;
+
+ waitcursor(1);
+
+ vfd= BLI_vfontdata_from_psfont(pf);
+
+ if (vfd) {
+ vfont = alloc_libblock(&G.main->vfont, ID_VF, filename);
+ vfont->data = vfd;
+
+ BLI_strncpy(vfont->name, name, sizeof(vfont->name));
+
+ // if autopack is on store the packedfile in de font structure
+ if (!is_builtin && (G.fileflags & G_AUTOPACK)) {
+ vfont->packedfile = pf;
+ }
+ }
+ if (!vfont || vfont->packedfile != pf) {
+ freePackedFile(pf);
+ }
+
+ waitcursor(0);
+ }
+
+ return vfont;
+}
+
+static void buildchar(Curve *cu, unsigned char ascii, float ofsx, float ofsy, float rot)
+{
+ BezTriple *bezt1, *bezt2;
+ Nurb *nu1, *nu2;
+ float *fp, fsize, shear, x, si, co;
+ VFontData *vfd;
+ int i;
+
+ vfd= vfont_get_data(cu->vfont);
+ if (!vfd) return;
+
+ /* maak een kopie op afstand ofsx, ofsy met shear*/
+ fsize= cu->fsize;
+ shear= cu->shear;
+ si= (float)sin(rot);
+ co= (float)cos(rot);
+
+ nu1 = vfd->nurbsbase[ascii].first;
+ while(nu1)
+ {
+ bezt1 = nu1->bezt;
+ if (bezt1){
+ nu2 =(Nurb*) MEM_mallocN(sizeof(Nurb),"duplichar_nurb");
+ if (nu2 == 0) break;
+ memcpy(nu2, nu1, sizeof(struct Nurb));
+ nu2->resolu= cu->resolu;
+ nu2->bp = 0;
+ nu2->knotsu = nu2->knotsv = 0;
+ nu2->flag= ME_SMOOTH;
+ /* nu2->trim.first = 0; */
+ /* nu2->trim.last = 0; */
+ i = nu2->pntsu;
+
+ bezt2 = (BezTriple*)MEM_mallocN(i * sizeof(BezTriple),"duplichar_bezt2");
+ if (bezt2 == 0){
+ MEM_freeN(nu2);
+ break;
+ }
+ memcpy(bezt2, bezt1, i * sizeof(struct BezTriple));
+ nu2->bezt = bezt2;
+
+ if (shear != 0.0) {
+ bezt2 = nu2->bezt;
+
+ for (i= nu2->pntsu; i > 0; i--) {
+ bezt2->vec[0][0] += shear * bezt2->vec[0][1];
+ bezt2->vec[1][0] += shear * bezt2->vec[1][1];
+ bezt2->vec[2][0] += shear * bezt2->vec[2][1];
+ bezt2++;
+ }
+ }
+ if(rot!=0.0) {
+ bezt2= nu2->bezt;
+ for (i=nu2->pntsu; i > 0; i--) {
+ fp= bezt2->vec[0];
+
+ x= fp[0];
+ fp[0]= co*x + si*fp[1];
+ fp[1]= -si*x + co*fp[1];
+ x= fp[3];
+ fp[3]= co*x + si*fp[4];
+ fp[4]= -si*x + co*fp[4];
+ x= fp[6];
+ fp[6]= co*x + si*fp[7];
+ fp[7]= -si*x + co*fp[7];
+
+ bezt2++;
+ }
+ }
+ bezt2 = nu2->bezt;
+
+ for (i= nu2->pntsu; i > 0; i--) {
+ fp= bezt2->vec[0];
+
+ fp[0]= (fp[0]+ofsx)*fsize;
+ fp[1]= (fp[1]+ofsy)*fsize;
+ fp[3]= (fp[3]+ofsx)*fsize;
+ fp[4]= (fp[4]+ofsy)*fsize;
+ fp[6]= (fp[6]+ofsx)*fsize;
+ fp[7]= (fp[7]+ofsy)*fsize;
+ bezt2++;
+ }
+
+ BLI_addtail(&(cu->nurb), nu2);
+ }
+ nu1 = nu1->next;
+ }
+}
+
+
+struct chartrans *text_to_curve(Object *ob, int mode)
+{
+ VFont *vfont;
+ VFontData *vfd;
+ Curve *cu, *cucu;
+ struct chartrans *chartransdata, *ct;
+ float distfac, tabfac, ctime, dtime, tvec[4], vec[4], rotvec[3], minx, maxx, miny, maxy;
+ float cmat[3][3], timeofs, si, co, sizefac;
+ float *f, maxlen=0, xof, yof, xtrax, linedist, *linedata, *linedata2;
+ int i, slen, oldflag;
+ short cnr=0, lnr=0;
+ char ascii, *mem;
+
+ /* opmerking: berekeningen altijd tot en met de '\0' van de string omdat
+ de cursor op die plek moet kunnen staan */
+
+ if(ob->type!=OB_FONT) return 0;
+
+ cu= ob->data;
+
+ vfont= cu->vfont;
+ if (vfont==0) return 0;
+ if (cu->str==0) return 0;
+
+ vfd= vfont_get_data(vfont);
+ if (!vfd) return 0;
+
+ /* aantal regels tellen */
+ mem= cu->str;
+ slen = strlen(mem);
+ cu->lines= 1;
+ for (i= 0; i<=slen; i++, mem++) {
+ ascii = *mem;
+ if(ascii== '\n' || ascii== '\r') cu->lines++;
+ }
+
+ /* bereken ofset en rotatie van iedere letter */
+ ct = chartransdata =
+ (struct chartrans*)MEM_callocN((slen+1)* sizeof(struct chartrans),"buildtext");
+ linedata= MEM_mallocN(sizeof(float)*cu->lines,"buildtext2");
+ linedata2= MEM_mallocN(sizeof(float)*cu->lines,"buildtext2");
+ xof= cu->xof;
+ yof= cu->yof;
+
+ xtrax= 0.5f*cu->spacing-0.5f;
+ linedist= cu->linedist;
+
+ for (i = 0 ; i<=slen ; i++) {
+ ascii = cu->str[i];
+ if(ascii== '\n' || ascii== '\r' || ascii==0) {
+ ct->xof= xof;
+ ct->yof= yof;
+ ct->linenr= lnr;
+ ct->charnr= cnr;
+
+ /* alleen lege regels mogen kleiner dan 1 zijn */
+ if( linedist<1.0) {
+ if(i<slen && (cu->str[i+1]=='\r' || cu->str[i+1]=='\n')) yof-= linedist;
+ else yof-= 1.0;
+ }
+ else yof-= linedist;
+
+ maxlen= MAX2(maxlen, xof);
+ linedata[lnr]= xof;
+ linedata2[lnr]= cnr;
+ xof= cu->xof;
+ lnr++;
+ cnr= 0;
+ }
+ else if(ascii==9) { /* TAB */
+ ct->xof= xof;
+ ct->yof= yof;
+ ct->linenr= lnr;
+ ct->charnr= cnr++;
+
+ tabfac= (xof-cu->xof+0.01f);
+ tabfac= (float)(2.0*ceil(tabfac/2.0));
+ xof= cu->xof+tabfac;
+ }
+ else {
+ ct->xof= xof;
+ ct->yof= yof;
+ ct->linenr= lnr;
+ ct->charnr= cnr++;
+
+ xof += vfd->width[ascii] + xtrax;
+ }
+ ct++;
+ }
+
+ /* met alle fontsettings plekken letters berekenen */
+ if(cu->spacemode!=CU_LEFT && lnr>1) {
+ ct= chartransdata;
+
+ if(cu->spacemode==CU_RIGHT) {
+ for(i=0;i<lnr;i++) linedata[i]= maxlen-linedata[i];
+ for (i=0; i<=slen; i++) {
+ ct->xof+= linedata[ct->linenr];
+ ct++;
+ }
+ } else if(cu->spacemode==CU_MIDDLE) {
+ for(i=0;i<lnr;i++) linedata[i]= (maxlen-linedata[i])/2;
+ for (i=0; i<=slen; i++) {
+ ct->xof+= linedata[ct->linenr];
+ ct++;
+ }
+ } else if(cu->spacemode==CU_FLUSH) {
+ for(i=0;i<lnr;i++)
+ if(linedata2[i]>1)
+ linedata[i]= (maxlen-linedata[i])/(linedata2[i]-1);
+ for (i=0; i<=slen; i++) {
+ ct->xof+= ct->charnr*linedata[ct->linenr];
+ ct++;
+ }
+ }
+ }
+
+ /* TEXT ON CURVE */
+ if(cu->textoncurve) {
+ cucu= cu->textoncurve->data;
+
+ oldflag= cucu->flag;
+ cucu->flag |= (CU_PATH+CU_FOLLOW);
+
+ if(cucu->path==0) calc_curvepath(cu->textoncurve);
+ if(cucu->path) {
+
+
+ Mat3CpyMat4(cmat, cu->textoncurve->obmat);
+ sizefac= Normalise(cmat[0])/cu->fsize;
+
+ minx=miny= 1.0e20f;
+ maxx=maxy= -1.0e20f;
+ ct= chartransdata;
+ for (i=0; i<=slen; i++, ct++) {
+ if(minx>ct->xof) minx= ct->xof;
+ if(maxx<ct->xof) maxx= ct->xof;
+ if(miny>ct->yof) miny= ct->yof;
+ if(maxy<ct->yof) maxy= ct->yof;
+ }
+
+ /* we zetten de x-coordinaat exact op de curve, de y wordt geroteerd */
+
+ /* de lengte correctie */
+ distfac= sizefac*cucu->path->totdist/(maxx-minx);
+ timeofs= 0.0;
+
+ if(distfac > 1.0) {
+ /* pad langer dan tekst: spacemode doet mee */
+ distfac= 1.0f/distfac;
+
+ if(cu->spacemode==CU_RIGHT) {
+ timeofs= 1.0f-distfac;
+ }
+ else if(cu->spacemode==CU_MIDDLE) {
+ timeofs= (1.0f-distfac)/2.0f;
+ }
+ else if(cu->spacemode==CU_FLUSH) distfac= 1.0f;
+
+ }
+ else distfac= 1.0;
+
+ distfac/= (maxx-minx);
+
+ timeofs+= distfac*cu->xof; /* niet cyclic */
+
+ ct= chartransdata;
+ for (i=0; i<=slen; i++, ct++) {
+
+ /* roteren rond centrum letter */
+ ascii = cu->str[i];
+ dtime= distfac*0.35f*vfd->width[ascii]; /* Waarom is 0.5 te groot? */
+ dtime= distfac*0.0f*vfd->width[ascii]; /* Waarom is 0.5 te groot? */
+
+ ctime= timeofs + distfac*( ct->xof - minx);
+ CLAMP(ctime, 0.0, 1.0);
+
+ /* de goede plek EN de goede rotatie apart berekenen */
+ where_on_path(cu->textoncurve, ctime, vec, tvec);
+ where_on_path(cu->textoncurve, ctime+dtime, tvec, rotvec);
+
+ VecMulf(vec, sizefac);
+
+ ct->rot= (float)(M_PI-atan2(rotvec[1], rotvec[0]));
+
+ si= (float)sin(ct->rot);
+ co= (float)cos(ct->rot);
+
+ yof= ct->yof;
+
+ ct->xof= vec[0] + si*yof;
+ ct->yof= vec[1] + co*yof;
+
+ }
+ cucu->flag= oldflag;
+ }
+ }
+
+
+ if(mode==FO_CURSUP || mode==FO_CURSDOWN) {
+ /* 2: curs omhoog
+ 3: curs omlaag */
+ ct= chartransdata+cu->pos;
+
+ if(mode==FO_CURSUP && ct->linenr==0);
+ else if(mode==FO_CURSDOWN && ct->linenr==lnr);
+ else {
+ if(mode==FO_CURSUP) lnr= ct->linenr-1;
+ else lnr= ct->linenr+1;
+ cnr= ct->charnr;
+ /* zoek karakter met lnr en cnr */
+ cu->pos= 0;
+ ct= chartransdata;
+ for (i= 0; i<slen; i++) {
+ if(ct->linenr==lnr) {
+ if(ct->charnr==cnr) break;
+ if( (ct+1)->charnr==0) break;
+ }
+ else if(ct->linenr>lnr) break;
+ cu->pos++;
+ ct++;
+ }
+ }
+ }
+
+ /* eerst cursor */
+ if(ob==G.obedit) {
+ ct= chartransdata+cu->pos;
+ si= (float)sin(ct->rot);
+ co= (float)cos(ct->rot);
+
+ f= G.textcurs[0];
+
+ f[0]= cu->fsize*(-0.1f*co + ct->xof);
+ f[1]= cu->fsize*(0.1f*si + ct->yof);
+
+ f[2]= cu->fsize*(0.1f*co + ct->xof);
+ f[3]= cu->fsize*(-0.1f*si + ct->yof);
+
+ f[4]= cu->fsize*( 0.1f*co + 0.8f*si + ct->xof);
+ f[5]= cu->fsize*(-0.1f*si + 0.8f*co + ct->yof);
+
+ f[6]= cu->fsize*(-0.1f*co + 0.8f*si + ct->xof);
+ f[7]= cu->fsize*( 0.1f*si + 0.8f*co + ct->yof);
+
+ }
+
+ if(mode==0) {
+ /* nurbdata maken */
+
+ freeNurblist(&cu->nurb);
+
+ ct= chartransdata;
+ for (i= 0; i<slen; i++) {
+ ascii = cu->str[i];
+ buildchar(cu, ascii, ct->xof, ct->yof, ct->rot);
+ ct++;
+ }
+ }
+
+ MEM_freeN(linedata);
+ MEM_freeN(linedata2);
+
+ if(mode==FO_DUPLI) {
+ return chartransdata;
+ }
+
+ MEM_freeN(chartransdata);
+ return 0;
+}
+
+
+/* ***************** DUPLI ***************** */
+
+static Object *find_family_object(Object **obar, char *family, char ch)
+{
+ Object *ob;
+ int flen;
+
+ if( obar[ch] ) return obar[ch];
+
+ flen= strlen(family);
+
+ ob= G.main->object.first;
+ while(ob) {
+ if( ob->id.name[flen+2]==ch ) {
+ if( strncmp(ob->id.name+2, family, flen)==0 ) break;
+ }
+ ob= ob->id.next;
+ }
+
+ obar[ch]= ob;
+
+ return ob;
+}
+
+
+void font_duplilist(Object *par)
+{
+ extern ListBase duplilist;
+ Object *ob, *newob, *obar[256];
+ Curve *cu;
+ struct chartrans *ct, *chartransdata;
+ float vec[3], pmat[4][4], fsize, xof, yof;
+ int slen, a;
+
+ Mat4CpyMat4(pmat, par->obmat);
+
+ /* in par staat een familienaam, deze gebruiken om objecten te vinden */
+
+ chartransdata= text_to_curve(par, FO_DUPLI);
+ if(chartransdata==0) return;
+
+ memset(obar, 0, 256*4);
+
+ cu= par->data;
+ slen= strlen(cu->str);
+ fsize= cu->fsize;
+ xof= cu->xof;
+ yof= cu->yof;
+
+ ct= chartransdata;
+ set_displist_onlyzero(1);
+
+ for(a=0; a<slen; a++, ct++) {
+
+ ob= find_family_object(obar, cu->family, cu->str[a]);
+ if(ob) {
+
+ makeDispList(ob);
+
+ vec[0]= fsize*(ct->xof - xof);
+ vec[1]= fsize*(ct->yof - yof);
+ vec[2]= 0.0;
+
+ Mat4MulVecfl(pmat, vec);
+
+ newob= MEM_mallocN(sizeof(Object), "newobj dupli");
+ memcpy(newob, ob, sizeof(Object));
+ newob->flag |= OB_FROMDUPLI;
+ newob->id.newid= (ID *)par; /* duplicator bewaren */
+ newob->totcol= par->totcol; /* voor give_current_material */
+
+ Mat4CpyMat4(newob->obmat, par->obmat);
+ VECCOPY(newob->obmat[3], vec);
+
+ newob->parent= 0;
+ newob->track= 0;
+
+ BLI_addtail(&duplilist, newob);
+ }
+
+ }
+ set_displist_onlyzero(0);
+ MEM_freeN(chartransdata);
+}
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
new file mode 100644
index 00000000000..6f01d028326
--- /dev/null
+++ b/source/blender/blenkernel/intern/group.c
@@ -0,0 +1,329 @@
+/* group.c sept 2000
+ * - cleaned up mar-01 nzc
+ *
+ *
+ * ton roosendaal
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_group_types.h"
+#include "DNA_object_types.h"
+#include "DNA_ipo_types.h"
+
+#include "BLI_blenlib.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BKE_library.h"
+#include "BKE_group.h"
+#include "BKE_object.h"
+#include "BKE_ipo.h"
+
+void free_object_key(ObjectKey *ok)
+{
+ if(ok->ipo) ok->ipo->id.us--;
+
+ MEM_freeN(ok);
+}
+
+void free_group_object(GroupObject *go)
+{
+ ObjectKey *ok;
+
+ while(go->okey.first) {
+ ok= go->okey.first;
+ BLI_remlink(&go->okey, ok);
+ free_object_key(ok);
+ }
+ MEM_freeN(go);
+}
+
+
+void free_group(Group *group)
+{
+ /* don't free group itself */
+ GroupObject *go;
+
+ BLI_freelistN(&group->gkey);
+
+ while(group->gobject.first) {
+ go= group->gobject.first;
+ BLI_remlink(&group->gobject, go);
+ free_group_object(go);
+ }
+
+}
+
+Group *add_group()
+{
+ Group *group;
+
+ group = alloc_libblock(&G.main->group, ID_GR, "Group");
+ return group;
+}
+
+/* assumes 'ok' is unitialized */
+void object_to_obkey(Object *ob, ObjectKey *ok)
+{
+ ok->partype= ob->partype;
+ ok->par1= ob->par1;
+ ok->par2= ob->par2;
+ ok->par3= ob->par3;
+
+ ok->parent= ob->parent;
+ ok->track= ob->track;
+
+ ok->ipo= copy_ipo(ob->ipo);
+
+ memcpy(ok->loc, ob->loc, 7*3*sizeof(float));
+ memcpy(ok->quat, ob->quat, 2*4*sizeof(float));
+ memcpy(ok->obmat, ob->obmat, 3*4*4*sizeof(float));
+
+ ok->lay= ob->lay;
+ ok->transflag= ob->transflag;
+ ok->trackflag= ob->transflag;
+ ok->upflag= ob->upflag;
+ ok->sf= ob->sf;
+ ok->ctime= ob->ctime;
+
+
+}
+
+void obkey_to_object(ObjectKey *ok, Object *ob)
+{
+ ob->partype= ok->partype;
+ ob->par1= ok->par1;
+ ob->par2= ok->par2;
+ ob->par3= ok->par3;
+
+ ob->parent= ok->parent;
+ ob->track= ok->track;
+
+ /* pretty tricky, this makes ob->ipo blocks with users 'hanging around' */
+ if(ob->ipo) {
+ free_libblock_us(&G.main->ipo, ob->ipo);
+ }
+ ob->ipo= copy_ipo(ok->ipo);
+
+ memcpy(ob->loc, ok->loc, 7*3*sizeof(float));
+ memcpy(ob->quat, ok->quat, 2*4*sizeof(float));
+ memcpy(ob->obmat, ok->obmat, 3*4*4*sizeof(float));
+
+ ob->lay= ok->lay;
+ ob->transflag= ok->transflag;
+ ob->trackflag= ok->transflag;
+ ob->upflag= ok->upflag;
+ ob->sf= ok->sf;
+ ob->ctime= ok->ctime;
+}
+
+/* current ob position */
+void add_object_key(GroupObject *go, GroupKey *gk)
+{
+ ObjectKey *ok;
+
+ /* check if there already is a key */
+ ok= go->okey.first;
+ while(ok) {
+ if(ok->gkey == gk) break;
+ ok= ok->next;
+ }
+
+ if(ok) {
+ BLI_remlink(&go->okey, ok);
+ free_object_key(ok);
+ }
+ ok= MEM_mallocN(sizeof(ObjectKey), "objectkey");
+ ok->gkey= gk;
+
+ object_to_obkey(go->ob, ok);
+
+ BLI_addtail(&go->okey, ok);
+
+}
+
+/* external */
+void add_to_group(Group *group, Object *ob)
+{
+ GroupObject *go;
+ GroupKey *gk;
+
+ /* check if the object has been added already */
+ go= group->gobject.first;
+ while(go) {
+ if(go->ob==ob) return;
+ go= go->next;
+ }
+
+ go= MEM_callocN(sizeof(GroupObject), "groupobject");
+ BLI_addtail( &group->gobject, go);
+
+ go->ob= ob;
+
+ /* keys? */
+ gk= group->gkey.first;
+ while(gk) {
+ add_object_key(go, gk);
+ gk= gk->next;
+ }
+}
+
+void rem_from_group(Group *group, Object *ob)
+{
+ GroupObject *go, *gon;
+ ObjectKey *ok;
+
+ go= group->gobject.first;
+ while(go) {
+ gon= go->next;
+ if(go->ob==ob) {
+ BLI_remlink(&group->gobject, go);
+ free_group_object(go);
+ }
+ else {
+ ok= go->okey.first;
+ while(ok) {
+ if(ok->parent==ob) ok->parent= NULL;
+ if(ok->track==ob) ok->track= NULL;
+ ok= ok->next;
+ }
+ }
+ go= gon;
+ }
+}
+
+void add_group_key(Group *group)
+{
+ GroupObject *go;
+ GroupKey *gk;
+ int nr=10;
+ extern char colname_array[][20]; /* material.c */
+
+ gk= group->gkey.first;
+ while(gk) {
+ nr++;
+ gk= gk->next;
+ }
+
+ gk= MEM_callocN(sizeof(GroupKey), "groupkey");
+ BLI_addtail(&group->gkey, gk);
+ strcpy(gk->name, colname_array[ nr % 120 ]);
+
+ go= group->gobject.first;
+ while(go) {
+ add_object_key(go, gk);
+ go= go->next;
+ }
+
+ group->active= gk;
+}
+
+void set_object_key(Object *ob, ObjectKey *ok)
+{
+ obkey_to_object(ok, ob);
+}
+
+void set_group_key(Group *group)
+{
+ /* sets active */
+ GroupObject *go;
+ ObjectKey *ok;
+
+ if(group->active==NULL) return;
+
+ go= group->gobject.first;
+ while(go) {
+ ok= go->okey.first;
+ while(ok) {
+ if(ok->gkey==group->active) {
+ set_object_key(go->ob, ok);
+ break;
+ }
+ ok= ok->next;
+ }
+ go= go->next;
+ }
+
+}
+
+Group *find_group(Object *ob)
+{
+ Group *group= G.main->group.first;
+ GroupObject *go;
+
+ while(group) {
+
+ go= group->gobject.first;
+ while(go) {
+ if(go->ob==ob) return group;
+ go= go->next;
+ }
+ group= group->id.next;
+ }
+ return NULL;
+}
+
+void set_group_key_name(Group *group, char *name)
+{
+ GroupKey *gk;
+
+ if(group==NULL) return;
+
+ gk= group->gkey.first;
+ while(gk) {
+ if(strcmp(name, gk->name)==0) break;
+ gk= gk->next;
+ }
+
+ if(gk) {
+ group->active= gk;
+ set_group_key(group);
+ }
+}
+
+void set_group_key_frame(Group *group, float frame)
+{
+ GroupObject *go;
+
+ if(group==NULL) return;
+
+ go= group->gobject.first;
+ while(go) {
+ where_is_object_time(go->ob, frame);
+ go= go->next;
+ }
+}
diff --git a/source/blender/blenkernel/intern/ika.c b/source/blender/blenkernel/intern/ika.c
new file mode 100644
index 00000000000..885c64f0397
--- /dev/null
+++ b/source/blender/blenkernel/intern/ika.c
@@ -0,0 +1,596 @@
+
+/* ika.c MIXED MODEL
+ *
+ * april 96
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+/* types */
+#include "DNA_ika_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+/* functions */
+#include "BKE_blender.h"
+#include "BKE_library.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_ika.h"
+
+/* Let's go! */
+#define TOLER 0.000076
+#define CLAMP(a, b, c) if((a)<(b)) (a)=(b); else if((a)>(c)) (a)=(c)
+
+
+void unlink_ika(Ika *ika)
+{
+ /* loskoppelen: */
+
+
+}
+
+/* niet Ika zelf vrijgeven */
+void free_ika(Ika *ika)
+{
+
+ /* unimplemented!!! */
+ unlink_ika(ika);
+
+ BLI_freelistN(&ika->limbbase);
+
+ if(ika->def) MEM_freeN(ika->def);
+}
+
+Ika *add_ika()
+{
+ Ika *ika;
+
+ ika= alloc_libblock(&G.main->ika, ID_IK, "Ika");
+ ika->flag = IK_GRABEFF | IK_XYCONSTRAINT;
+
+ ika->xyconstraint= 0.5f;
+ ika->mem= 0.3f;
+ ika->iter= 6;
+
+ return ika;
+}
+
+Ika *copy_ika(Ika *ika)
+{
+ Ika *ikan;
+
+ ikan= copy_libblock(ika);
+
+ duplicatelist(&ikan->limbbase, &ika->limbbase);
+
+ ikan->def= MEM_dupallocN(ikan->def);
+
+ return ikan;
+}
+
+void make_local_ika(Ika *ika)
+{
+ Object *ob;
+ Ika *ikan;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(ika->id.lib==0) return;
+ if(ika->id.us==1) {
+ ika->id.lib= 0;
+ ika->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ika, 0);
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==ika) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ ika->id.lib= 0;
+ ika->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ika, 0);
+ }
+ else if(local && lib) {
+ ikan= copy_ika(ika);
+ ikan->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==ika) {
+
+ if(ob->id.lib==0) {
+ ob->data= ikan;
+ ikan->id.us++;
+ ika->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+int count_limbs(Object *ob)
+{
+ int tot=0;
+ Ika *ika;
+ Limb *li;
+
+ if(ob->type!=OB_IKA) return 0;
+ ika= ob->data;
+
+ li= ika->limbbase.first;
+ while(li) {
+ tot++;
+ li= li->next;
+ }
+ return tot;
+}
+
+/* ************************************************** */
+
+
+/* aan hand van eff[] de len en alpha */
+void calc_limb(Limb *li)
+{
+ Limb *prev= li;
+ float vec[2], alpha= 0.0;
+
+ /* alpha van 'parents' */
+ while( (prev=prev->prev) ) {
+ alpha+= prev->alpha;
+ }
+
+ if(li->prev) {
+ vec[0]= -li->prev->eff[0];
+ vec[1]= -li->prev->eff[1];
+ }
+ else vec[0]= vec[1]= 0.0;
+
+ vec[0]+= li->eff[0];
+ vec[1]+= li->eff[1];
+
+ li->alpha= (float)atan2(vec[1], vec[0]) - alpha;
+ li->len= (float)sqrt(vec[0]*vec[0] + vec[1]*vec[1]);
+
+}
+
+/* aan hand van len en alpha worden de eindpunten berekend */
+void calc_ika(Ika *ika, Limb *li)
+{
+ float alpha=0.0, co, si;
+
+ if(li) {
+ Limb *prev= li;
+ while((prev=prev->prev)) {
+ alpha+= prev->alpha;
+ }
+ }
+ else li= ika->limbbase.first;
+
+ while(li) {
+ if(li->alpha != li->alpha) li->alpha= 0.0f; /* NaN patch */
+
+ alpha+= li->alpha;
+
+ co= (float)cos(alpha);
+ si= (float)sin(alpha);
+
+ li->eff[0]= co*li->len;
+ li->eff[1]= si*li->len;
+
+ if(li->prev) {
+ li->eff[0]+= li->prev->eff[0];
+ li->eff[1]+= li->prev->eff[1];
+ }
+
+ if(li->next==0) {
+ ika->eff[0]= li->eff[0];
+ ika->eff[1]= li->eff[1];
+ }
+
+ li= li->next;
+ }
+}
+
+void init_defstate_ika(Object *ob)
+{
+ Ika *ika;
+ Limb *li;
+
+ ika= ob->data;
+ ika->totx= 0.0;
+ ika->toty= 0.0;
+ li= ika->limbbase.first;
+
+ calc_ika(ika, 0); /* correcte eindpunten */
+
+ while(li) {
+ li->alphao= li->alpha;
+ li->leno= li->len;
+
+ li= li->next;
+ }
+ ika->eff[2]= 0.0;
+ VecMat4MulVecfl(ika->effg, ob->obmat, ika->eff);
+}
+
+void itterate_limb(Ika *ika, Limb *li)
+{
+ float da, n1[2], n2[2], len1, len2;
+
+ if(li->prev) {
+ n1[0]= ika->eff[0] - li->prev->eff[0];
+ n1[1]= ika->eff[1] - li->prev->eff[1];
+ n2[0]= ika->effn[0] - li->prev->eff[0];
+ n2[1]= ika->effn[1] - li->prev->eff[1];
+ }
+ else {
+ n1[0]= ika->eff[0];
+ n1[1]= ika->eff[1];
+ n2[0]= ika->effn[0];
+ n2[1]= ika->effn[1];
+ }
+ len1= (float)sqrt(n1[0]*n1[0] + n1[1]*n1[1]);
+ len2= (float)sqrt(n2[0]*n2[0] + n2[1]*n2[1]);
+
+ da= (1.0f-li->fac)*saacos( (n1[0]*n2[0]+n1[1]*n2[1])/(len1*len2) );
+
+ if(n1[0]*n2[1] < n1[1]*n2[0]) da= -da;
+
+ li->alpha+= da;
+
+}
+
+void rotate_ika(Object *ob, Ika *ika)
+{
+ Limb *li;
+ float len2, da, n1[2], n2[2];
+
+ /* terug roteren */
+ euler_rot(ob->rot, -ika->toty, 'y');
+ ika->toty= 0.0;
+
+ where_is_object(ob);
+
+ Mat4Invert(ob->imat, ob->obmat);
+ VecMat4MulVecfl(ika->effn, ob->imat, ika->effg);
+
+ li= ika->limbbase.last;
+ if(li==0) return;
+
+ n1[0]= ika->eff[0];
+ n2[0]= ika->effn[0];
+ n2[1]= ika->effn[2];
+
+ len2= (float)sqrt(n2[0]*n2[0] + n2[1]*n2[1]);
+
+ if(len2>TOLER) {
+ da= (n2[0])/(len2);
+ if(n1[0]<0.0) da= -da;
+
+ /* als de x comp bijna nul is kan dit gebeuren */
+ if(da<=-1.0+TOLER || da>=1.0) ;
+ else {
+
+ da= saacos( da );
+ if(n1[0]*n2[1] > 0.0) da= -da;
+
+ euler_rot(ob->rot, da, 'y');
+ ika->toty= da;
+ }
+ }
+}
+
+void rotate_ika_xy(Object *ob, Ika *ika)
+{
+ Limb *li;
+ float ang, da, n1[3], n2[3], axis[3], quat[4];
+
+ /* terug roteren */
+ euler_rot(ob->rot, -ika->toty, 'y');
+ euler_rot(ob->rot, -ika->totx, 'x');
+
+ where_is_object(ob);
+
+ Mat4Invert(ob->imat, ob->obmat);
+ VecMat4MulVecfl(ika->effn, ob->imat, ika->effg);
+
+ li= ika->limbbase.last;
+ if(li==0) return;
+
+ /* ika->eff = old situation */
+ /* ika->effn = desired situation */
+
+ *(n1)= *(ika->effn);
+ *(n1+1)= *(ika->effn+1);
+ *(n1+2)= 0.0;
+
+ *(n2)= *(ika->effn);
+ *(n2+1)= *(ika->effn+1);
+ *(n2+2)= *(ika->effn+2);
+
+ Normalise(n1);
+ Normalise(n2);
+
+ ang= n1[0]*n2[0] + n1[1]*n2[1] + n1[2]*n2[2];
+ ang= saacos(ang);
+
+ if(ang<-0.0000001 || ang>0.00000001) {
+ Crossf(axis, n1, n2);
+ Normalise(axis);
+ quat[0]= (float)cos(0.5*ang);
+ da= (float)sin(0.5*ang);
+ quat[1]= da*axis[0];
+ quat[2]= da*axis[1];
+ quat[3]= da*axis[2];
+
+ QuatToEul(quat, axis);
+
+ ika->totx= axis[0];
+ CLAMP(ika->totx, -ika->xyconstraint, ika->xyconstraint);
+ ika->toty= axis[1];
+ CLAMP(ika->toty, -ika->xyconstraint, ika->xyconstraint);
+ }
+
+ euler_rot(ob->rot, ika->totx, 'x');
+ euler_rot(ob->rot, ika->toty, 'y');
+}
+
+void itterate_ika(Object *ob)
+{
+ Ika *ika;
+ Limb *li;
+ int it = 0;
+
+ ika= ob->data;
+ if((ika->flag & IK_GRABEFF)==0) return;
+
+ disable_where_script(1);
+ /* memory: grote tijdsprongen afvangen */
+ it= abs(ika->lastfra - G.scene->r.cfra);
+ ika->lastfra= G.scene->r.cfra;
+ if(it>10) {
+
+ /* one itteration extra */
+ itterate_ika(ob);
+ }
+ else {
+ li= ika->limbbase.first;
+ while(li) {
+ li->alpha= (1.0f-ika->mem)*li->alpha + ika->mem*li->alphao;
+ if(li->fac==1.0f) li->fac= 0.05f; /* oude files: kan weg in juni 96 */
+ li= li->next;
+ }
+ }
+ calc_ika(ika, 0);
+
+ /* effector heeft parent? */
+ if(ika->parent) {
+
+ if(ika->partype==PAROBJECT) {
+ if(ika->parent->ctime != (float) G.scene->r.cfra) where_is_object(ika->parent);
+ *(ika->effg)= *(ika->parent->obmat[3]);
+ *(ika->effg+1)= *(ika->parent->obmat[3]+1);
+ *(ika->effg+2)= *(ika->parent->obmat[3]+2);
+ }
+ else {
+ what_does_parent1(ika->parent, ika->partype, ika->par1, 0, 0);
+ *(ika->effg)= *(workob.obmat[3]);
+ *(ika->effg+1)= *(workob.obmat[3]+1);
+ *(ika->effg+2)= *(workob.obmat[3]+2);
+ }
+ }
+
+
+ /* y-as goed draaien */
+ if(ika->flag & IK_XYCONSTRAINT)
+ rotate_ika_xy(ob, ika);
+ else
+ rotate_ika(ob, ika);
+
+ it= ika->iter;
+ while(it--) {
+
+ where_is_object(ob);
+ Mat4Invert(ob->imat, ob->obmat);
+ VecMat4MulVecfl(ika->effn, ob->imat, ika->effg);
+ /* forward: dan gaan ook de eerste limbs */
+ li= ika->limbbase.first;
+ while(li) {
+
+ itterate_limb(ika, li);
+
+ /* zet je calc_ika() buiten deze lus: lange kettingen instabiel */
+ calc_ika(ika, li);
+
+ li= li->next;
+ }
+
+ where_is_object(ob);
+ Mat4Invert(ob->imat, ob->obmat);
+ VecMat4MulVecfl(ika->effn, ob->imat, ika->effg);
+
+ /* backward */
+ li= ika->limbbase.last;
+ while(li) {
+
+ itterate_limb(ika, li);
+
+ /* zet je calc_ika() buiten deze lus: lange kettingen instabiel */
+ calc_ika(ika, li);
+
+ li= li->prev;
+ }
+ }
+
+ disable_where_script(0);
+}
+
+
+void do_all_ikas()
+{
+ Base *base = 0;
+
+ base= G.scene->base.first;
+ while(base) {
+
+ if(base->object->type==OB_IKA) itterate_ika(base->object);
+
+ base= base->next;
+ }
+}
+
+void do_all_visible_ikas()
+{
+ Base *base = 0;
+
+ base= G.scene->base.first;
+ while(base) {
+ if(base->lay & G.scene->lay) {
+ if(base->object->type==OB_IKA) itterate_ika(base->object);
+ }
+ base= base->next;
+ }
+}
+
+/* ******************** DEFORM ************************ */
+
+
+void init_skel_deform(Object *par, Object *ob)
+{
+ Deform *def;
+ Ika *ika;
+ int a;
+
+ /* deform:
+ *
+ * ob_vec * ob_obmat * def_imat (weight fie) * def_obmat * ob_imat = ob_vec'
+ *
+ * <----- premat ----> <---- postmat ---->
+ */
+
+ if(par->type!=OB_IKA) return;
+
+ Mat4Invert(ob->imat, ob->obmat);
+
+ ika= par->data;
+ a= ika->totdef;
+ def= ika->def;
+ while(a--) {
+
+ what_does_parent1(def->ob, def->partype, def->par1, def->par2, def->par3);
+
+ Mat4MulMat4(def->premat, ob->obmat, def->imat);
+ Mat4MulMat4(def->postmat, workob.obmat, ob->imat);
+
+ def++;
+ }
+}
+
+
+void calc_skel_deform(Ika *ika, float *co)
+{
+ Deform *def;
+ int a;
+ float totw=0.0, weight, fac, len, vec[3], totvec[3];
+
+ def= ika->def;
+ if(def==0) return;
+ a= ika->totdef;
+ totvec[0]=totvec[1]=totvec[2]= 0.0;
+
+ while(a--) {
+
+ VecMat4MulVecfl(vec, def->premat, co);
+
+ len= (float)sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
+
+ if(def->vec[0]==0.0f) len= 2.0f*len;
+ else len= len + (float)sqrt( (vec[0]+def->vec[0])*(vec[0]+def->vec[0]) + vec[1]*vec[1] + vec[2]*vec[2]);
+
+ /* def->vec[0]= len limb */
+
+ weight= 1.0f/(0.001f+len);
+ weight*= weight;
+ weight*= weight;
+ weight*= def->fac;
+
+ len -= def->vec[0];
+
+ if(def->dist != 0.0) {
+ if(len >= def->dist) {
+ weight= 0.0;
+ }
+ else {
+ fac= (def->dist - len)/def->dist;
+ weight*= fac;
+ }
+ }
+ if(weight > 0.0) {
+ Mat4MulVecfl(def->postmat, vec);
+
+ VecMulf(vec, weight);
+ VecAddf(totvec, totvec, vec);
+
+ totw+= weight;
+ }
+ def++;
+ }
+
+ if(totw==0.0) return;
+
+ co[0]= totvec[0]/totw;
+ co[1]= totvec[1]/totw;
+ co[2]= totvec[2]/totw;
+
+}
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
new file mode 100644
index 00000000000..7e3e5eca3aa
--- /dev/null
+++ b/source/blender/blenkernel/intern/image.c
@@ -0,0 +1,1486 @@
+/* image.c MIX MODEL
+ *
+ * maart 95
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <math.h>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_texture_types.h"
+#include "DNA_image_types.h"
+#include "DNA_packedFile_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BKE_image.h"
+#include "BKE_bmfont.h"
+#include "BKE_screen.h"
+#include "BKE_texture.h"
+#include "BKE_packedFile.h"
+#include "BKE_library.h"
+
+void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2);
+void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2);
+float square_rctf(rctf *rf);
+float clipx_rctf(rctf *rf, float x1, float x2);
+float clipy_rctf(rctf *rf, float y1, float y2);
+void boxsample(struct ImBuf *ibuf,
+ float minx, float miny, float maxx, float maxy,
+ float *rcol, float *gcol, float *bcol, float *acol);
+void boxsampleclip(struct ImBuf *ibuf, rctf *rf, float *rcol,
+ float *gcol, float *bcol, float *acol);
+void filtersample(struct ImBuf *ibuf,
+ float fx, float fy,
+ float *rcol, float *gcol, float *bcol, float *acol);
+
+
+
+/* If defined: check arguments on call */
+/* #define IMAGE_C_ARG_CHECK */
+
+/* Communicate with texture channels. */
+extern float Tin, Tr, Tg, Tb, Ta;
+
+int Talpha;
+int imaprepeat, imapextend;
+
+
+/*
+ *
+ * Talpha==TRUE betekent: lees alpha uit plaatje. Dit betekent niet dat Ta
+ * niet gebruikt moet worden, hier kan info over rand van image in staan!
+ *
+ */
+
+void free_image_buffers(Image *ima)
+{
+ int a;
+
+ if(ima->ibuf) {
+ if (ima->ibuf->userdata) {
+ MEM_freeN(ima->ibuf->userdata);
+ ima->ibuf->userdata = 0;
+ }
+ IMB_freeImBuf(ima->ibuf);
+ ima->ibuf= 0;
+ }
+ if(ima->anim) IMB_free_anim(ima->anim);
+ ima->anim= 0;
+
+ for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) {
+ if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]);
+ ima->mipmap[a]= 0;
+ }
+
+ free_realtime_image(ima);
+}
+
+
+void free_image(Image *ima)
+{
+
+ free_image_buffers(ima);
+ if (ima->packedfile) {
+ freePackedFile(ima->packedfile);
+ ima->packedfile = NULL;
+ }
+}
+
+
+Image *add_image(char *name)
+{
+ Image *ima;
+ int file, len;
+ char *libname, str[256], strtest[256];
+
+ strcpy(str, name);
+ BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
+
+ file= open(str, O_BINARY|O_RDONLY);
+ if(file== -1) return 0;
+ close(file);
+
+ /* eerst zoeken naar eenzelfde ima */
+ ima= G.main->image.first;
+ while(ima) {
+ strcpy(strtest, ima->name);
+ BLI_convertstringcode(strtest, G.sce, G.scene->r.cfra);
+ if( strcmp(strtest, str)==0 ) {
+ if(ima->anim==0 || ima->id.us==0) {
+ strcpy(ima->name, name); /* for stringcode */
+ ima->id.us++;
+ ima->ok= 1;
+ return ima;
+ }
+ }
+ ima= ima->id.next;
+ }
+
+ len= strlen(name);
+
+ while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\') len--;
+ libname= name+len;
+
+ ima= alloc_libblock(&G.main->image, ID_IM, libname);
+ strcpy(ima->name, name);
+ ima->ok= 1;
+
+ ima->xrep= ima->yrep= 1;
+
+ return ima;
+}
+
+void free_unused_animimages()
+{
+ Image *ima, *nima;
+
+ ima= G.main->image.first;
+ while(ima) {
+ nima= ima->id.next;
+ if(ima->id.us==0) {
+ if(ima->flag & IMA_FROMANIM) free_libblock(&G.main->image, ima);
+ }
+ ima= nima;
+ }
+}
+
+
+/* *********** LEZEN EN SCHRIJVEN ************** */
+
+void makepicstring(char *string, int frame)
+{
+ short i,len;
+ char num[10], *extension;
+
+ if (string==0) return;
+
+ extension= "";
+
+ strcpy(string, G.scene->r.pic);
+ BLI_convertstringcode(string, G.sce, G.scene->r.cfra);
+
+ len= strlen(string);
+
+ /* kan ook: sprintf(num, "%04d", frame); */
+
+ i=4-sprintf(num,"%d",frame);
+ for(;i>0;i--){
+ string[len]='0';
+ len++;
+ }
+ string[len]=0;
+ strcat(string,num);
+
+ if(G.scene->r.imtype== R_IRIS) {
+ extension= ".rgb";
+ }
+ else if(G.scene->r.imtype==R_IRIZ) {
+ extension= ".rgb";
+ }
+ else if(G.scene->r.imtype==R_PNG) {
+ extension= ".png";
+ }
+ else if(G.scene->r.imtype==R_TARGA) {
+ extension= ".tga";
+ }
+ else if(G.scene->r.imtype==R_RAWTGA) {
+ extension= ".tga";
+ }
+ else if(G.scene->r.imtype==R_JPEG90) {
+ extension= ".jpg";
+ }
+
+ if(G.scene->r.scemode & R_EXTENSION) strcat(string, extension);
+
+}
+
+/* ******** IMAGWRAPPING INIT ************* */
+
+void converttopremul(struct ImBuf *ibuf)
+{
+ int x, y, val;
+ char *cp;
+
+ if(ibuf==0) return;
+ if(ibuf->depth==24) { /* alpha op 255 zetten */
+
+ cp= (char *)(ibuf->rect);
+ for(y=0; y<ibuf->y; y++) {
+ for(x=0; x<ibuf->x; x++, cp+=4) {
+ cp[3]= 255;
+ }
+ }
+ return;
+ }
+
+ cp= (char *)(ibuf->rect);
+ for(y=0; y<ibuf->y; y++) {
+ for(x=0; x<ibuf->x; x++, cp+=4) {
+ if(cp[3]==0) {
+ cp[0]= cp[1]= cp[2]= 0;
+ }
+ else if(cp[3]!=255) {
+ val= cp[3];
+ cp[0]= (cp[0]*val)>>8;
+ cp[1]= (cp[1]*val)>>8;
+ cp[2]= (cp[2]*val)>>8;
+ }
+ }
+ }
+}
+
+
+
+void makemipmap(Image *ima)
+{
+ struct ImBuf *ibuf;
+ int minsize, curmap=0;
+
+ ibuf= ima->ibuf;
+ minsize= MIN2(ibuf->x, ibuf->y);
+
+ while(minsize>3 && curmap<BLI_ARRAY_NELEMS(ima->mipmap)) {
+
+ ibuf= IMB_dupImBuf(ibuf);
+ IMB_filter(ibuf);
+ ima->mipmap[curmap]= (struct ImBuf *)IMB_onehalf(ibuf);
+ IMB_freeImBuf(ibuf);
+ ibuf= ima->mipmap[curmap];
+
+ curmap++;
+ minsize= MIN2(ibuf->x, ibuf->y);
+ }
+}
+
+struct anim *openanim(char * name, int flags)
+{
+ struct anim * anim;
+ struct ImBuf * ibuf;
+
+ anim = IMB_open_anim(name, flags);
+ if (anim == 0) return(0);
+
+
+ ibuf = IMB_anim_absolute(anim, 0);
+ if (ibuf == 0) {
+ printf("anim_absolute 0 failed\n");
+ IMB_free_anim(anim);
+ return(0);
+ }
+ IMB_freeImBuf(ibuf);
+
+ return(anim);
+}
+
+int calcimanr(int cfra, Tex *tex)
+{
+ int imanr, len, a, fra, dur;
+
+ /* hier (+fie_ima/2-1) zorgt ervoor dat correct wordt gedeeld */
+
+ if(tex->frames==0) return 1;
+
+ cfra= cfra-tex->sfra+1;
+
+ /* cyclic */
+ if(tex->len==0) len= (tex->fie_ima*tex->frames)/2;
+ else len= tex->len;
+
+ if(tex->imaflag & TEX_ANIMCYCLIC) {
+ cfra= ( (cfra) % len );
+ if(cfra < 0) cfra+= len;
+ if(cfra==0) cfra= len;
+ }
+
+ if(cfra<1) cfra= 1;
+ else if(cfra>len) cfra= len;
+
+ /* omzetten current frame naar current field */
+ cfra= 2*(cfra);
+ if(R.flag & R_SEC_FIELD) cfra++;
+
+
+ /* transformeren naar images space */
+ imanr= (cfra+tex->fie_ima-2)/tex->fie_ima;
+
+ if(imanr>tex->frames) imanr= tex->frames;
+ imanr+= tex->offset;
+
+ /* zijn er plaatjes die langer duren? */
+ for(a=0; a<4; a++) {
+ if(tex->fradur[a][0]) {
+
+ fra= tex->fradur[a][0];
+ dur= tex->fradur[a][1]-1;
+
+ while(dur>0 && imanr>fra) {
+ imanr--;
+ dur--;
+ }
+ }
+ }
+
+
+ return imanr;
+}
+
+void do_laseroptics_patch(ImBuf *ibuf)
+{
+ char *rt;
+ float fac;
+ int a, val;
+
+ rt= (char *)ibuf->rect;
+ a= ibuf->x*ibuf->y;
+
+ if(ibuf->flags & IB_fields) a+= a;
+
+ while(a--) {
+
+ fac= (rt[1]+rt[2]+rt[3])/765.0f;
+ val= (int)((255.0/0.8)*(fac-0.1));
+
+ if(val<0) val= 0; else if(val>255) val= 255;
+
+ rt[0]= rt[1]= rt[2]= rt[3]= val;
+
+ rt+= 4;
+ }
+}
+
+void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */
+{
+ struct ImBuf * tbuf1, * tbuf2;
+
+ if (ibuf == 0) return;
+ if (ibuf->flags & IB_fields) return;
+ ibuf->flags |= IB_fields;
+
+ if (ibuf->rect) {
+ /* kopieen aanmaken */
+ tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0);
+ tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0);
+
+ ibuf->x *= 2;
+ /* These rectop calls are broken!!! I added a trailing 0 arg... */
+ IMB_rectop(tbuf1, ibuf, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+ IMB_rectop(tbuf2, ibuf, 0, 0, tbuf2->x, 0, 32767, 32767, IMB_rectcpy, 0);
+
+ ibuf->x /= 2;
+ IMB_rectop(ibuf, tbuf1, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+ IMB_rectop(ibuf, tbuf2, 0, tbuf2->y, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+
+ IMB_freeImBuf(tbuf1);
+ IMB_freeImBuf(tbuf2);
+ }
+ ibuf->y /= 2;
+}
+
+void de_interlace_st(struct ImBuf *ibuf) /* standard fields */
+{
+ struct ImBuf * tbuf1, * tbuf2;
+
+ if (ibuf == 0) return;
+ if (ibuf->flags & IB_fields) return;
+ ibuf->flags |= IB_fields;
+
+ if (ibuf->rect) {
+ /* kopieen aanmaken */
+ tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0);
+ tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0);
+
+ ibuf->x *= 2;
+ /* These are brolenm as well... */
+ IMB_rectop(tbuf1, ibuf, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+ IMB_rectop(tbuf2, ibuf, 0, 0, tbuf2->x, 0, 32767, 32767, IMB_rectcpy, 0);
+
+ ibuf->x /= 2;
+ IMB_rectop(ibuf, tbuf2, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+ IMB_rectop(ibuf, tbuf1, 0, tbuf2->y, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+
+ IMB_freeImBuf(tbuf1);
+ IMB_freeImBuf(tbuf2);
+ }
+ ibuf->y /= 2;
+}
+
+/*
+load_image handles reading the image from disk or from the packedfile.
+*/
+
+void load_image(Image * ima, int flags, char *relabase, int framenum)
+{
+ char name[FILE_MAXDIR + FILE_MAXFILE];
+
+ if (ima->ibuf == NULL) {
+
+ // is there a PackedFile with this image ?;
+ if (ima->packedfile) {
+ ima->ibuf = IMB_ibImageFromMemory((int *) ima->packedfile->data, ima->packedfile->size, flags);
+ } else {
+ strcpy(name, ima->name);
+ BLI_convertstringcode(name, relabase, framenum);
+
+ ima->ibuf = IMB_loadiffname(name , flags);
+ }
+ // check if the image is a font image...
+ // printf("Checking for font\n");
+
+ if (ima->ibuf) {
+ detectBitmapFont(ima->ibuf);
+ }
+ }
+}
+
+void ima_ibuf_is_nul(Tex *tex)
+{
+ void (*de_interlacefunc)(struct ImBuf *ibuf);
+ Image *ima;
+ int a, fra;
+ char str[FILE_MAXDIR+FILE_MAXFILE], *cp;
+
+ ima= tex->ima;
+ if(ima==0) return;
+
+ waitcursor(1);
+
+ strcpy(str, ima->name);
+ BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
+
+ if(tex->imaflag & TEX_STD_FIELD) de_interlacefunc= de_interlace_st;
+ else de_interlacefunc= de_interlace_ng;
+
+ if(tex->imaflag & TEX_ANIM5) {
+
+ if(ima->anim==0) ima->anim = openanim(str, IB_cmap | IB_rect);
+ if (ima->anim) {
+
+ ima->lastquality= R.osa;
+ fra= ima->lastframe-1;
+ if(fra<0) fra= 0;
+ ima->ibuf = IMB_anim_absolute(ima->anim, fra);
+
+ /* patch ivm textbutton met naam ima (B_NAMEIMA) */
+ if(ima->ibuf) {
+ strcpy(ima->ibuf->name, ima->name);
+ if (tex->imaflag & TEX_FIELDS) de_interlacefunc(ima->ibuf);
+ }
+ }
+ else error("Not an anim");
+
+ } else {
+ // create a packedfile for this image when autopack is on
+ // for performance (IMB_loadiffname uses mmap) we don't do this by default
+ if ((ima->packedfile == NULL) && (G.fileflags & G_AUTOPACK)) {
+ ima->packedfile = newPackedFile(str);
+ }
+
+ load_image(ima, IB_rect, G.sce, G.scene->r.cfra);
+
+ if (tex->imaflag & TEX_FIELDS) de_interlacefunc(ima->ibuf);
+
+ ima->lastquality= R.osa;
+ }
+
+ if(ima->ibuf) {
+
+ /* stringcodes ook in ibuf. ibuf->name wordt als 'undo' gebruikt (buttons.c) */
+ strcpy(ima->ibuf->name, ima->name);
+
+ if(ima->ibuf->cmap) {
+
+ if(tex->imaflag & TEX_ANIM5) {
+
+ if(tex->imaflag & TEX_MORKPATCH) {
+ /**** PATCH OM KLEUR 2 GOED TE KUNNEN ZETTEN MORKRAMIA */
+ if(ima->ibuf->maxcol > 4) {
+ cp= (char *)(ima->ibuf->cmap+2);
+ cp[0]= 0x80;
+ }
+ }
+
+ IMB_applycmap(ima->ibuf);
+ IMB_convert_rgba_to_abgr(ima->ibuf->x*ima->ibuf->y, ima->ibuf->rect);
+
+ }
+
+ converttopremul(ima->ibuf);
+ }
+
+ if(R.osa) {
+
+ if(tex->imaflag & TEX_ANTISCALE) {
+ IMB_clever_double(ima->ibuf);
+ IMB_antialias(ima->ibuf);
+ }
+ else if(tex->imaflag & TEX_ANTIALI) IMB_antialias(ima->ibuf);
+ }
+
+ if(tex->imaflag & TEX_LASOPPATCH) {
+ do_laseroptics_patch(ima->ibuf);
+ }
+
+ }
+
+ if(ima->ibuf==0) ima->ok= 0;
+
+ for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) {
+ if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]);
+ ima->mipmap[a]= 0;
+ }
+
+ if((R.flag & R_RENDERING)==0) waitcursor(0);
+
+}
+
+
+
+/* *********** IMAGEWRAPPING ****************** */
+
+
+int imagewrap(Tex *tex, float *texvec)
+{
+ Image *ima;
+ struct ImBuf *ibuf;
+ float fx, fy, val1, val2, val3;
+ int ofs, x, y;
+ char *rect;
+
+ ima= tex->ima;
+
+ if(ima==0 || ima->ok== 0) {
+ Tin= Ta= Tr= Tg= Tb= 0.0;
+ return 0;
+ }
+
+ if(ima->ibuf==0) ima_ibuf_is_nul(tex);
+
+ if (ima->ok) {
+
+ ibuf = ima->ibuf;
+
+ if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
+ ibuf->rect+= (ibuf->x*ibuf->y);
+ }
+
+ if(tex->imaflag & TEX_IMAROT) {
+ fy= texvec[0];
+ fx= texvec[1];
+ }
+ else {
+ fx= texvec[0];
+ fy= texvec[1];
+ }
+
+ x = (int)(fx*ibuf->x);
+ y = (int)(fy*ibuf->y);
+
+ if(tex->extend == TEX_CLIPCUBE) {
+ if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0 || texvec[2]>1.0) {
+ Tin= 0;
+ return 0;
+ }
+ }
+ else if(tex->extend == TEX_CLIP) {
+ if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) {
+ Tin= 0;
+ return 0;
+ }
+ }
+ else {
+ if(tex->extend==TEX_EXTEND) {
+ if(x>=ibuf->x) x = ibuf->x-1;
+ else if(x<0) x= 0;
+ }
+ else {
+ x= x % ibuf->x;
+ if(x<0) x+= ibuf->x;
+ }
+ if(tex->extend==TEX_EXTEND) {
+ if(y>=ibuf->y) y = ibuf->y-1;
+ else if(y<0) y= 0;
+ }
+ else {
+ y= y % ibuf->y;
+ if(y<0) y+= ibuf->y;
+ }
+ }
+
+ ofs = y * ibuf->x + x;
+ rect = (char *)( ibuf->rect+ ofs);
+
+ Talpha= 0;
+ if(tex->imaflag & TEX_USEALPHA) {
+ if(tex->imaflag & TEX_CALCALPHA);
+ else Talpha= 1;
+ }
+
+ Tr = ((float)rect[0])/255.0f;
+ Tg = ((float)rect[1])/255.0f;
+ Tb = ((float)rect[2])/255.0f;
+
+ if(tex->nor) {
+ /* bump: drie samples nemen */
+ val1= Tr+Tg+Tb;
+
+ if(x<ibuf->x-1) {
+ rect+=4;
+ val2= ((float)(rect[0]+rect[1]+rect[2]))/255.0f;
+ rect-=4;
+ }
+ else val2= val1;
+
+ if(y<ibuf->y-1) {
+ rect+= 4*ibuf->x;
+ val3= ((float)(rect[0]+rect[1]+rect[2]))/255.0f;
+ }
+ else val3= val1;
+
+ /* niet x en y verwisselen! */
+ tex->nor[0]= (val1-val2);
+ tex->nor[1]= (val1-val3);
+ }
+
+ BRICONRGB;
+
+ if(Talpha) Ta= Tin= ((float)rect[3])/255.0f;
+ else if(tex->imaflag & TEX_CALCALPHA) {
+ Ta= Tin= MAX3(Tr, Tg, Tb);
+ }
+ else Ta= Tin= 1.0;
+
+ if(tex->flag & TEX_NEGALPHA) Ta= 1.0f-Ta;
+
+ if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
+ ibuf->rect-= (ibuf->x*ibuf->y);
+ }
+ }
+
+ if(tex->flag & TEX_COLORBAND) do_colorband(tex->coba);
+
+ if(tex->nor) return 3;
+ else return 1;
+}
+
+void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2)
+/* rctf *stack; */
+/* short *count; */
+/* float x1, x2; */
+{
+ rctf *rf, *newrct;
+ short a;
+
+ a= *count;
+ rf= stack;
+ for(;a>0;a--) {
+ if(rf->xmin<x1) {
+ if(rf->xmax<x1) {
+ rf->xmin+= (x2-x1);
+ rf->xmax+= (x2-x1);
+ }
+ else {
+ if(rf->xmax>x2) rf->xmax= x2;
+ newrct= stack+ *count;
+ (*count)++;
+
+ newrct->xmax= x2;
+ newrct->xmin= rf->xmin+(x2-x1);
+ newrct->ymin= rf->ymin;
+ newrct->ymax= rf->ymax;
+
+ if(newrct->xmin==newrct->xmax) (*count)--;
+
+ rf->xmin= x1;
+ }
+ }
+ else if(rf->xmax>x2) {
+ if(rf->xmin>x2) {
+ rf->xmin-= (x2-x1);
+ rf->xmax-= (x2-x1);
+ }
+ else {
+ if(rf->xmin<x1) rf->xmin= x1;
+ newrct= stack+ *count;
+ (*count)++;
+
+ newrct->xmin= x1;
+ newrct->xmax= rf->xmax-(x2-x1);
+ newrct->ymin= rf->ymin;
+ newrct->ymax= rf->ymax;
+
+ if(newrct->xmin==newrct->xmax) (*count)--;
+
+ rf->xmax= x2;
+ }
+ }
+ rf++;
+ }
+
+}
+
+void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2)
+/* rctf *stack; */
+/* short *count; */
+/* float y1, y2; */
+{
+ rctf *rf, *newrct;
+ short a;
+
+ a= *count;
+ rf= stack;
+ for(;a>0;a--) {
+ if(rf->ymin<y1) {
+ if(rf->ymax<y1) {
+ rf->ymin+= (y2-y1);
+ rf->ymax+= (y2-y1);
+ }
+ else {
+ if(rf->ymax>y2) rf->ymax= y2;
+ newrct= stack+ *count;
+ (*count)++;
+
+ newrct->ymax= y2;
+ newrct->ymin= rf->ymin+(y2-y1);
+ newrct->xmin= rf->xmin;
+ newrct->xmax= rf->xmax;
+
+ if(newrct->ymin==newrct->ymax) (*count)--;
+
+ rf->ymin= y1;
+ }
+ }
+ else if(rf->ymax>y2) {
+ if(rf->ymin>y2) {
+ rf->ymin-= (y2-y1);
+ rf->ymax-= (y2-y1);
+ }
+ else {
+ if(rf->ymin<y1) rf->ymin= y1;
+ newrct= stack+ *count;
+ (*count)++;
+
+ newrct->ymin= y1;
+ newrct->ymax= rf->ymax-(y2-y1);
+ newrct->xmin= rf->xmin;
+ newrct->xmax= rf->xmax;
+
+ if(newrct->ymin==newrct->ymax) (*count)--;
+
+ rf->ymax= y2;
+ }
+ }
+ rf++;
+ }
+
+}
+
+
+
+float square_rctf(rctf *rf)
+/* rctf *rf; */
+{
+ float x, y;
+
+ x= rf->xmax- rf->xmin;
+ y= rf->ymax- rf->ymin;
+ return (x*y);
+}
+
+float clipx_rctf(rctf *rf, float x1, float x2)
+/* rctf *rf; */
+/* float x1, x2; */
+{
+ float size;
+
+ size= rf->xmax - rf->xmin;
+
+ if(rf->xmin<x1) {
+ rf->xmin= x1;
+ }
+ if(rf->xmax>x2) {
+ rf->xmax= x2;
+ }
+ if(rf->xmin > rf->xmax) {
+ rf->xmin = rf->xmax;
+ return 0.0;
+ }
+ else if(size!=0.0) {
+ return (rf->xmax - rf->xmin)/size;
+ }
+ return 1.0;
+}
+
+float clipy_rctf(rctf *rf, float y1, float y2)
+/* rctf *rf; */
+/* float y1, y2; */
+{
+ float size;
+
+ size= rf->ymax - rf->ymin;
+/* PRINT(f, size); */
+ if(rf->ymin<y1) {
+ rf->ymin= y1;
+ }
+ if(rf->ymax>y2) {
+ rf->ymax= y2;
+ }
+/* PRINT(f, size); */
+ if(rf->ymin > rf->ymax) {
+ rf->ymin = rf->ymax;
+ return 0.0;
+ }
+ else if(size!=0.0) {
+ return (rf->ymax - rf->ymin)/size;
+ }
+ return 1.0;
+
+}
+
+void boxsampleclip(struct ImBuf *ibuf, rctf *rf, float *rcol,
+ float *gcol, float *bcol, float *acol) /* return kleur 0.0-1.0 */
+/* struct ImBuf *ibuf; */
+/* rctf *rf; */
+/* float *rcol, *gcol, *bcol, *acol; */
+{
+ /* sample box, is reeds geclipt en minx enz zijn op ibuf size gezet.
+ * Vergroot uit met antialiased edges van de pixels */
+
+ float muly,mulx,div;
+ int ofs;
+ int x, y, startx, endx, starty, endy;
+ char *rect;
+
+ startx= (int)floor(rf->xmin);
+ endx= (int)floor(rf->xmax);
+ starty= (int)floor(rf->ymin);
+ endy= (int)floor(rf->ymax);
+
+ if(startx < 0) startx= 0;
+ if(starty < 0) starty= 0;
+ if(endx>=ibuf->x) endx= ibuf->x-1;
+ if(endy>=ibuf->y) endy= ibuf->y-1;
+
+ if(starty==endy && startx==endx) {
+
+ ofs = starty*ibuf->x + startx;
+ rect = (char *)(ibuf->rect +ofs);
+ *rcol= ((float)rect[0])/255.0f;
+ *gcol= ((float)rect[1])/255.0f;
+ *bcol= ((float)rect[2])/255.0f;
+ /* alpha is globaal, reeds gezet in functie imagewraposa() */
+ if(Talpha) {
+ *acol= ((float)rect[3])/255.0f;
+ }
+ }
+ else {
+ div= *rcol= *gcol= *bcol= *acol= 0.0;
+ for(y=starty;y<=endy;y++) {
+ ofs = y*ibuf->x +startx;
+ rect = (char *)(ibuf->rect+ofs);
+
+ muly= 1.0;
+
+ if(starty==endy);
+ else {
+ if(y==starty) muly= 1.0f-(rf->ymin - y);
+ if(y==endy) muly= (rf->ymax - y);
+ }
+ if(startx==endx) {
+ mulx= muly;
+ if(Talpha) *acol+= mulx*rect[3];
+ *rcol+= mulx*rect[0];
+ *gcol+= mulx*rect[1];
+ *bcol+= mulx*rect[2];
+ div+= mulx;
+ }
+ else {
+ for(x=startx;x<=endx;x++) {
+ mulx= muly;
+ if(x==startx) mulx*= 1.0f-(rf->xmin - x);
+ if(x==endx) mulx*= (rf->xmax - x);
+
+ if(mulx==1.0) {
+ if(Talpha) *acol+= rect[3];
+ *rcol+= rect[0];
+ *gcol+= rect[1];
+ *bcol+= rect[2];
+ div+= 1.0;
+ }
+ else {
+ if(Talpha) *acol+= mulx*rect[3];
+ *rcol+= mulx*rect[0];
+ *gcol+= mulx*rect[1];
+ *bcol+= mulx*rect[2];
+ div+= mulx;
+ }
+ rect+=4;
+ }
+ }
+ }
+ if(div!=0.0) {
+ div*= 255.0;
+
+ *bcol/= div;
+ *gcol/= div;
+ *rcol/= div;
+
+ if(Talpha) *acol/= div;
+ }
+ else {
+ *rcol= *gcol= *bcol= *acol= 0.0;
+ }
+ }
+}
+
+void boxsample(struct ImBuf *ibuf,
+ float minx, float miny, float maxx, float maxy,
+ float *rcol, float *gcol, float *bcol, float *acol) /* return kleur 0.0-1.0 */
+/* struct ImBuf *ibuf; */
+/* float minx, miny, maxx, maxy; */
+/* float *rcol, *gcol, *bcol, *acol; */
+{
+ /* Sample box, doet clip. minx enz lopen van 0.0 - 1.0 .
+ * Vergroot uit met antialiased edges van de pixels.
+ * Als global imaprepeat is gezet, worden
+ * de weggeclipte stukken ook gesampled.
+ */
+ rctf *rf, stack[8];
+ float opp, tot, r, g, b, a, alphaclip= 1.0;
+ short count=1;
+
+ rf= stack;
+ rf->xmin= minx*(ibuf->x);
+ rf->xmax= maxx*(ibuf->x);
+ rf->ymin= miny*(ibuf->y);
+ rf->ymax= maxy*(ibuf->y);
+
+ if(imapextend);
+ else if(imaprepeat) clipx_rctf_swap(stack, &count, 0.0, (float)(ibuf->x));
+ else {
+ alphaclip= clipx_rctf(rf, 0.0, (float)(ibuf->x));
+
+ if(alphaclip<=0.0) {
+ *rcol= *bcol= *gcol= *acol= 0.0;
+ return;
+ }
+ }
+
+ if(imapextend);
+ else if(imaprepeat) clipy_rctf_swap(stack, &count, 0.0, (float)(ibuf->y));
+ else {
+ alphaclip*= clipy_rctf(rf, 0.0, (float)(ibuf->y));
+
+ if(alphaclip<=0.0) {
+ *rcol= *bcol= *gcol= *acol= 0.0;
+ return;
+ }
+ }
+
+ if(count>1) {
+ tot= *rcol= *bcol= *gcol= *acol= 0.0;
+ while(count--) {
+ boxsampleclip(ibuf, rf, &r, &g, &b, &a);
+
+ opp= square_rctf(rf);
+ tot+= opp;
+
+ *rcol+= opp*r;
+ *gcol+= opp*g;
+ *bcol+= opp*b;
+ if(Talpha) *acol+= opp*a;
+ rf++;
+ }
+ if(tot!= 0.0) {
+ *rcol/= tot;
+ *gcol/= tot;
+ *bcol/= tot;
+ if(Talpha) *acol/= tot;
+ }
+ }
+ else {
+ boxsampleclip(ibuf, rf, rcol, gcol, bcol, acol);
+ }
+
+ if(Talpha==0) *acol= 1.0;
+
+ if(alphaclip!=1.0) {
+ /* this is for laer investigation, premul or not? */
+ /* *rcol*= alphaclip; */
+ /* *gcol*= alphaclip; */
+ /* *bcol*= alphaclip; */
+ *acol*= alphaclip;
+ }
+}
+
+void filtersample(struct ImBuf *ibuf,
+ float fx, float fy,
+ float *rcol, float *gcol, float *bcol, float *acol)
+ /* return kleur 0.0-1.0 */
+/* struct ImBuf *ibuf; */ /* fx en fy tussen 0.0 en 1.0 */
+/* float fx, fy; */
+/* float *rcol, *gcol, *bcol, *acol; */
+{
+ /* met weighted filter 3x3
+ * de linker of rechter kolom is altijd 0
+ * en de bovenste of onderste rij is altijd 0
+ */
+
+ int fac, fac1, fac2, fracx, fracy, filt[4];
+ int ix, iy, x4;
+ unsigned int r=0, g=0, b=0, a=0;
+ char *rowcol, *rfilt[4];
+
+ ix= (int)( 256.0*fx );
+ fracx= (ix & 255);
+ ix= (ix>>8);
+ iy= (int)( 256.0*fy );
+ fracy= (iy & 255);
+ iy= (iy>>8);
+
+ if(ix>=ibuf->x) ix= ibuf->x-1;
+ if(iy>=ibuf->y) iy= ibuf->y-1;
+
+ rowcol= (char *)(ibuf->rect+ iy*ibuf->x +ix);
+
+ rfilt[0]= rfilt[1]= rfilt[2]= rfilt[3]= rowcol;
+ x4= 4*ibuf->x;
+
+ if(fracx<128) {
+ if(ix>0) {
+ rfilt[0]-= 4;
+ rfilt[2]-=4;
+ }
+ else if(imaprepeat) {
+ rfilt[0]+= x4-4;
+ rfilt[2]+= x4-4;
+ }
+
+ if(fracy<128) {
+ /* geval linksonder */
+ fac1= 128+fracy;
+ fac2= 128-fracy;
+
+ if(iy>0) {
+ rfilt[3]-= x4;
+ rfilt[2]-= x4;
+ }
+ else if(imaprepeat) {
+ fac= x4*(ibuf->y-1) ;
+ rfilt[3]+= fac;
+ rfilt[2]+= fac;
+ }
+ }
+ else {
+ /* geval linksboven */
+ fac2= 384-fracy;
+ fac1= fracy-128;
+
+ if(iy<ibuf->y-1) {
+ rfilt[1]+= x4;
+ rfilt[0]+= x4;
+ }
+ else if(imaprepeat) {
+ fac= x4*(ibuf->y-1) ;
+ rfilt[1]-= fac;
+ rfilt[0]-= fac;
+ }
+ }
+
+ filt[1]=filt[3]= 128+ fracx;
+ filt[0]=filt[2]= 128- fracx;
+ filt[0]*= fac1;
+ filt[1]*= fac1;
+ filt[2]*= fac2;
+ filt[3]*= fac2;
+ }
+ else {
+ if(fracy<128) {
+ /* geval rechtsonder */
+ fac1= 128+fracy;
+ fac2= 128-fracy;
+
+ if(iy>0) {
+ rfilt[3]-= x4;
+ rfilt[2]-= x4;
+ }
+ else if(imaprepeat) {
+ fac= x4*(ibuf->y-1) ;
+ rfilt[3]+= fac;
+ rfilt[2]+= fac;
+ }
+ }
+ else {
+ /* geval rechtsboven */
+ fac2= 384-fracy;
+ fac1= fracy-128;
+
+ if(iy<ibuf->y-1) {
+ rfilt[1]+= x4;
+ rfilt[0]+= x4;
+ }
+ else if(imaprepeat) {
+ fac= x4*(ibuf->y-1) ;
+ rfilt[1]-= fac;
+ rfilt[0]-= fac;
+ }
+ }
+ filt[0]=filt[2]= 384-fracx;
+ filt[1]=filt[3]= fracx-128;
+ filt[0]*= fac1;
+ filt[1]*= fac1;
+ filt[2]*= fac2;
+ filt[3]*= fac2;
+
+ if(ix<ibuf->x-1) {
+ rfilt[1]+= 4;
+ rfilt[3]+=4;
+ }
+ else if(imaprepeat) {
+ rfilt[1]-= x4-4;
+ rfilt[3]-= x4-4;
+ }
+ }
+
+ for(fac=3; fac>=0; fac--) {
+ rowcol= rfilt[fac];
+ r+= filt[fac]*rowcol[0];
+ g+= filt[fac]*rowcol[1];
+ b+= filt[fac]*rowcol[2];
+ if(Talpha) a+= filt[fac]*rowcol[3]; /* alpha is globaal */
+ }
+ *rcol= ((float)r)/16777216.0f;
+ *gcol= ((float)g)/16777216.0f;
+ *bcol= ((float)b)/16777216.0f;
+ if(Talpha) *acol= ((float)a)/16777216.0f;
+
+}
+
+
+int imagewraposa(Tex *tex, float *texvec, float *dxt, float *dyt)
+{
+ struct Image *ima;
+ struct ImBuf *ibuf, *previbuf;
+ float fx, fy, minx, maxx, miny, maxy, dx, dy, fac1, fac2, fac3, fac4;
+ float maxd, pixsize, val1, val2, val3;
+ int curmap;
+
+#ifdef IMAGE_C_ARG_CHECK
+ if (!tex) {
+ printf("imagewraposa: null pointer to texture\n");
+ }
+#endif
+
+ ima= tex->ima;
+#ifdef IMAGE_C_ARG_CHECK
+ if (!ima) {
+ printf("imagewraposa: null pointer to image\n");
+ }
+#endif
+
+ Tin= Ta= Tr= Tg= Tb= 0.0;
+
+ if(ima==0 || ima->ok== 0) {
+ return 0;
+ }
+
+ if(ima->ibuf==0) ima_ibuf_is_nul(tex);
+
+ if (ima->ok) {
+
+ if(tex->imaflag & TEX_MIPMAP) {
+ if(ima->mipmap[0]==0) makemipmap(ima);
+ }
+
+ ibuf = ima->ibuf;
+
+ if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
+ ibuf->rect+= (ibuf->x*ibuf->y);
+ }
+
+ Talpha= 0;
+ if(tex->imaflag & TEX_USEALPHA) {
+ if(tex->imaflag & TEX_CALCALPHA);
+ else Talpha= 1;
+ }
+
+ if(tex->imaflag & TEX_IMAROT) {
+ fy= texvec[0];
+ fx= texvec[1];
+ }
+ else {
+ fx= texvec[0];
+ fy= texvec[1];
+ }
+
+
+ if(ibuf->flags & IB_fields) {
+ if(R.r.mode & R_FIELDS) { /* field render */
+ if(R.flag & R_SEC_FIELD) { /* correctie voor tweede field */
+ /* fac1= 0.5/( (float)ibuf->y ); */
+ /* fy-= fac1; */
+ }
+ else { /* eerste field */
+ fac1= 0.5f/( (float)ibuf->y );
+ fy+= fac1;
+ }
+ }
+ }
+
+ /* pixel coordinaten */
+
+ minx= MIN3(dxt[0],dyt[0],dxt[0]+dyt[0] );
+ maxx= MAX3(dxt[0],dyt[0],dxt[0]+dyt[0] );
+ miny= MIN3(dxt[1],dyt[1],dxt[1]+dyt[1] );
+ maxy= MAX3(dxt[1],dyt[1],dxt[1]+dyt[1] );
+
+ /* tex_sharper afgeschaft */
+
+ minx= tex->filtersize*(maxx-minx)/2.0f;
+ miny= tex->filtersize*(maxy-miny)/2.0f;
+
+ if(tex->imaflag & TEX_IMAROT) SWAP(float, minx, miny);
+
+ if(minx>0.25) minx= 0.25;
+ else if(minx<0.00001f) minx= 0.00001f; /* zijvlakken van eenheidskubus */
+ if(miny>0.25) miny= 0.25;
+ else if(miny<0.00001f) miny= 0.00001f;
+
+
+ /* repeat en clip */
+
+ /* let op: imaprepeat is globale waarde (zie boxsample) */
+ imaprepeat= (tex->extend==TEX_REPEAT);
+ imapextend= (tex->extend==TEX_EXTEND);
+
+
+ if(tex->extend == TEX_CLIPCUBE) {
+ if(fx+minx<0.0 || fy+miny<0.0 || fx-minx>1.0 || fy-miny>1.0 || texvec[2]<-1.0 || texvec[2]>1.0) {
+ Tin= 0;
+ return 0;
+ }
+ }
+ else if(tex->extend == TEX_CLIP) {
+ if(fx+minx<0.0 || fy+miny<0.0 || fx-minx>1.0 || fy-miny>1.0) {
+ Tin= 0.0;
+ return 0;
+ }
+ }
+ else {
+ if(tex->extend==TEX_EXTEND) {
+ if(fx>1.0) fx = 1.0;
+ else if(fx<0.0) fx= 0.0;
+ }
+ else {
+ if(fx>1.0) fx -= (int)(fx);
+ else if(fx<0.0) fx+= 1-(int)(fx);
+ }
+
+ if(tex->extend==TEX_EXTEND) {
+ if(fy>1.0) fy = 1.0;
+ else if(fy<0.0) fy= 0.0;
+ }
+ else {
+ if(fy>1.0) fy -= (int)(fy);
+ else if(fy<0.0) fy+= 1-(int)(fy);
+ }
+ }
+
+ /* keuze: */
+ if(tex->imaflag & TEX_MIPMAP) {
+
+ dx= minx;
+ dy= miny;
+ maxd= MAX2(dx, dy);
+ if(maxd>0.5) maxd= 0.5;
+
+ pixsize = 1.0f/ (float) MIN2(ibuf->x, ibuf->y);
+
+ curmap= 0;
+ previbuf= ibuf;
+ while(curmap<BLI_ARRAY_NELEMS(ima->mipmap) && ima->mipmap[curmap]) {
+ if(maxd < pixsize) break;
+ previbuf= ibuf;
+ ibuf= ima->mipmap[curmap];
+ pixsize= 1.0f / (float)MIN2(ibuf->x, ibuf->y); /* hier stond 1.0 */
+ curmap++;
+ }
+
+ if(previbuf!=ibuf || (tex->imaflag & TEX_INTERPOL)) {
+ /* minmaal 1 pixel sampelen */
+ if (minx < 0.5f / ima->ibuf->x) minx = 0.5f / ima->ibuf->x;
+ if (miny < 0.5f / ima->ibuf->y) miny = 0.5f / ima->ibuf->y;
+ }
+
+ if(tex->nor) {
+ /* beetje extra filter */
+ minx*= 1.35f;
+ miny*= 1.35f;
+
+ boxsample(ibuf, fx-2.0f*minx, fy-2.0f*miny, fx+minx, fy+miny, &Tr, &Tg, &Tb, &Ta);
+ val1= Tr+Tg+Tb;
+ boxsample(ibuf, fx-minx, fy-2.0f*miny, fx+2.0f*minx, fy+miny, &fac1, &fac2, &fac3, &fac4);
+ val2= fac1+fac2+fac3;
+ boxsample(ibuf, fx-2.0f*minx, fy-miny, fx+minx, fy+2.0f*miny, &fac1, &fac2, &fac3, &fac4);
+ val3= fac1+fac2+fac3;
+
+ if(previbuf!=ibuf) { /* interpoleren */
+
+ boxsample(previbuf, fx-2.0f*minx, fy-2.0f*miny, fx+minx, fy+miny, &fac1, &fac2, &fac3, &fac4);
+
+ /* rgb berekenen */
+ dx= 2.0f*(pixsize-maxd)/pixsize;
+ if(dx>=1.0f) {
+ Ta= fac4; Tb= fac3;
+ Tg= fac2; Tr= fac1;
+ }
+ else {
+ dy= 1.0f-dx;
+ Tb= dy*Tb+ dx*fac3;
+ Tg= dy*Tg+ dx*fac2;
+ Tr= dy*Tr+ dx*fac1;
+ if(Talpha) Ta= dy*Ta+ dx*fac4;
+ }
+
+ val1= dy*val1+ dx*(fac1+fac2+fac3);
+ boxsample(previbuf, fx-minx, fy-2.0f*miny, fx+2.0f*minx, fy+miny, &fac1, &fac2, &fac3, &fac4);
+ val2= dy*val2+ dx*(fac1+fac2+fac3);
+ boxsample(previbuf, fx-2.0f*minx, fy-miny, fx+minx, fy+2.0f*miny, &fac1, &fac2, &fac3, &fac4);
+ val3= dy*val3+ dx*(fac1+fac2+fac3);
+ }
+
+ /* niet x en y verwisselen! */
+ tex->nor[0]= (val1-val2);
+ tex->nor[1]= (val1-val3);
+
+ }
+ else {
+ maxx= fx+minx;
+ minx= fx-minx;
+ maxy= fy+miny;
+ miny= fy-miny;
+
+ boxsample(ibuf, minx, miny, maxx, maxy, &Tr, &Tg, &Tb, &Ta);
+
+ if(previbuf!=ibuf) { /* interpoleren */
+ boxsample(previbuf, minx, miny, maxx, maxy, &fac1, &fac2, &fac3, &fac4);
+
+ fx= 2.0f*(pixsize-maxd)/pixsize;
+
+ if(fx>=1.0) {
+ Ta= fac4; Tb= fac3;
+ Tg= fac2; Tr= fac1;
+ } else {
+ fy= 1.0f-fx;
+ Tb= fy*Tb+ fx*fac3;
+ Tg= fy*Tg+ fx*fac2;
+ Tr= fy*Tr+ fx*fac1;
+ if(Talpha) Ta= fy*Ta+ fx*fac4;
+ }
+ }
+ }
+ }
+ else {
+ if((tex->imaflag & TEX_INTERPOL)) {
+ /* minmaal 1 pixel sampelen */
+ if (minx < 0.5f / ima->ibuf->x) minx = 0.5f / ima->ibuf->x;
+ if (miny < 0.5f / ima->ibuf->y) miny = 0.5f / ima->ibuf->y;
+ }
+
+ if(tex->nor) {
+
+ /* beetje extra filter */
+ minx*= 1.35f;
+ miny*= 1.35f;
+
+ boxsample(ibuf, fx-2.0f*minx, fy-2.0f*miny, fx+minx, fy+miny, &Tr, &Tg, &Tb, &Ta);
+ val1= Tr+Tg+Tb;
+
+ boxsample(ibuf, fx-minx, fy-2.0f*miny, fx+2.0f*minx, fy+miny, &fac1, &fac2, &fac3, &fac4);
+ val2= fac1+fac2+fac3;
+
+ boxsample(ibuf, fx-2.0f*minx, fy-miny, fx+miny, fy+2.0f*miny, &fac1, &fac2, &fac3, &fac4);
+ val3= fac1+fac2+fac3;
+
+ /* niet x en y verwisselen! */
+ tex->nor[0]= (val1-val2);
+ tex->nor[1]= (val1-val3);
+
+ }
+ else {
+ boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, &Tr, &Tg, &Tb, &Ta);
+ }
+
+ }
+
+ BRICONRGB;
+
+ if(tex->imaflag & TEX_CALCALPHA) {
+ Ta= Tin= MAX3(Tr, Tg, Tb);
+ }
+ else Tin= Ta;
+ if(tex->flag & TEX_NEGALPHA) Ta= 1.0f-Ta;
+
+ if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
+ ibuf->rect-= (ibuf->x*ibuf->y);
+ }
+
+ }
+ else {
+ Tin= 0.0f;
+ return 0;
+ }
+
+ if(tex->flag & TEX_COLORBAND) do_colorband(tex->coba);
+
+ if(tex->nor) return 3;
+ else return 1;
+}
+
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
new file mode 100644
index 00000000000..cab1efba716
--- /dev/null
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -0,0 +1,1878 @@
+/* ipo.c MIXED MODEL
+ *
+ * jan 95
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ika_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_key_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_action_types.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+
+#include "BKE_main.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_curve.h"
+#include "BKE_object.h"
+#include "BKE_blender.h"
+#include "BKE_ipo.h"
+#include "BKE_constraint.h"
+
+#define SMALL -1.0e-10
+
+/* Dit array is ervoor zodat defines zoals OB_LOC_X niet persee 0 hoeft te zijn.
+ Ook voor toekomstige backward compatibility.
+ Zo kan met een for-next lus alles worden afgelopen */
+
+int co_ar[CO_TOTIPO]= {
+ CO_ENFORCE
+};
+
+int ob_ar[OB_TOTIPO]= {
+ OB_LOC_X, OB_LOC_Y, OB_LOC_Z, OB_DLOC_X, OB_DLOC_Y, OB_DLOC_Z,
+ OB_ROT_X, OB_ROT_Y, OB_ROT_Z, OB_DROT_X, OB_DROT_Y, OB_DROT_Z,
+ OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z, OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z,
+ OB_LAY, OB_TIME, OB_EFF_X, OB_EFF_Y, OB_EFF_Z, OB_COL_A
+};
+
+int ac_ar[AC_TOTIPO]= {
+ AC_LOC_X, AC_LOC_Y, AC_LOC_Z,
+ AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z,
+ AC_SIZE_X, AC_SIZE_Y, AC_SIZE_Z
+};
+
+int ma_ar[MA_TOTIPO]= {
+ MA_COL_R, MA_COL_G, MA_COL_B,
+ MA_SPEC_R, MA_SPEC_G, MA_SPEC_B,
+ MA_MIR_R, MA_MIR_G, MA_MIR_B,
+ MA_REF, MA_ALPHA, MA_EMIT, MA_AMB,
+ MA_SPEC, MA_HARD, MA_SPTR, MA_ANG,
+ MA_MODE, MA_HASIZE,
+
+ MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z,
+ MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z,
+ MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B,
+ MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF
+};
+
+int seq_ar[SEQ_TOTIPO]= {
+ SEQ_FAC1
+};
+
+int cu_ar[CU_TOTIPO]= {
+ CU_SPEED
+};
+
+int key_ar[KEY_TOTIPO]= {
+ KEY_SPEED, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+};
+
+int wo_ar[WO_TOTIPO]= {
+ WO_HOR_R, WO_HOR_G, WO_HOR_B, WO_ZEN_R, WO_ZEN_G, WO_ZEN_B,
+ WO_EXPOS, WO_MISI, WO_MISTDI, WO_MISTSTA, WO_MISTHI,
+ WO_STAR_R, WO_STAR_G, WO_STAR_B, WO_STARDIST, WO_STARSIZE,
+
+ MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z,
+ MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z,
+ MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B,
+ MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF
+};
+
+int la_ar[LA_TOTIPO]= {
+ LA_ENERGY, LA_COL_R, LA_COL_G, LA_COL_B,
+ LA_DIST, LA_SPOTSI, LA_SPOTBL,
+ LA_QUAD1, LA_QUAD2, LA_HALOINT,
+
+ MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z,
+ MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z,
+ MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B,
+ MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF
+};
+
+int cam_ar[CAM_TOTIPO]= {
+ CAM_LENS, CAM_STA, CAM_END
+};
+
+int snd_ar[SND_TOTIPO]= {
+ SND_VOLUME, SND_PITCH, SND_PANNING, SND_ATTEN
+};
+
+
+
+float frame_to_float(int cfra) /* zie ook bsystem_time in object.c */
+{
+ extern float bluroffs; /* object.c */
+ float ctime;
+
+ ctime= (float)cfra;
+ if(R.flag & R_SEC_FIELD) {
+ if((R.r.mode & R_FIELDSTILL)==0) ctime+= 0.5;
+ }
+ ctime+= bluroffs;
+ ctime*= G.scene->r.framelen;
+
+ return ctime;
+}
+
+/* niet ipo zelf vrijgeven */
+void free_ipo(Ipo *ipo)
+{
+ IpoCurve *icu;
+
+ icu= ipo->curve.first;
+ while(icu) {
+ if(icu->bezt) MEM_freeN(icu->bezt);
+ icu= icu->next;
+ }
+ BLI_freelistN(&ipo->curve);
+}
+
+Ipo *add_ipo(char *name, int idcode)
+{
+ Ipo *ipo;
+
+ ipo= alloc_libblock(&G.main->ipo, ID_IP, name);
+ ipo->blocktype= idcode;
+
+ return ipo;
+}
+
+Ipo *copy_ipo(Ipo *ipo)
+{
+ Ipo *ipon;
+ IpoCurve *icu;
+
+ if(ipo==0) return 0;
+
+ ipon= copy_libblock(ipo);
+
+ duplicatelist(&(ipon->curve), &(ipo->curve));
+
+ icu= ipon->curve.first;
+ while(icu) {
+ icu->bezt= MEM_dupallocN(icu->bezt);
+ icu= icu->next;
+ }
+
+ return ipon;
+}
+
+void make_local_obipo(Ipo *ipo)
+{
+ Object *ob;
+ Ipo *ipon;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->ipo==ipo) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ ipo->id.lib= 0;
+ ipo->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ipo, 0);
+ }
+ else if(local && lib) {
+ ipon= copy_ipo(ipo);
+ ipon->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->ipo==ipo) {
+
+ if(ob->id.lib==0) {
+ ob->ipo= ipon;
+ ipon->id.us++;
+ ipo->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+void make_local_matipo(Ipo *ipo)
+{
+ Material *ma;
+ Ipo *ipon;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->ipo==ipo) {
+ if(ma->id.lib) lib= 1;
+ else local= 1;
+ }
+ ma= ma->id.next;
+ }
+
+ if(local && lib==0) {
+ ipo->id.lib= 0;
+ ipo->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ipo, 0);
+ }
+ else if(local && lib) {
+ ipon= copy_ipo(ipo);
+ ipon->id.us= 0;
+
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->ipo==ipo) {
+
+ if(ma->id.lib==0) {
+ ma->ipo= ipon;
+ ipon->id.us++;
+ ipo->id.us--;
+ }
+ }
+ ma= ma->id.next;
+ }
+ }
+}
+
+void make_local_keyipo(Ipo *ipo)
+{
+ Key *key;
+ Ipo *ipon;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ key= G.main->key.first;
+ while(key) {
+ if(key->ipo==ipo) {
+ if(key->id.lib) lib= 1;
+ else local= 1;
+ }
+ key= key->id.next;
+ }
+
+ if(local && lib==0) {
+ ipo->id.lib= 0;
+ ipo->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ipo, 0);
+ }
+ else if(local && lib) {
+ ipon= copy_ipo(ipo);
+ ipon->id.us= 0;
+
+ key= G.main->key.first;
+ while(key) {
+ if(key->ipo==ipo) {
+
+ if(key->id.lib==0) {
+ key->ipo= ipon;
+ ipon->id.us++;
+ ipo->id.us--;
+ }
+ }
+ key= key->id.next;
+ }
+ }
+}
+
+
+void make_local_ipo(Ipo *ipo)
+{
+
+ if(ipo->id.lib==0) return;
+ if(ipo->id.us==1) {
+ ipo->id.lib= 0;
+ ipo->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ipo, 0);
+ return;
+ }
+
+ if(ipo->blocktype==ID_OB) make_local_obipo(ipo);
+ else if(ipo->blocktype==ID_MA) make_local_matipo(ipo);
+ else if(ipo->blocktype==ID_KE) make_local_keyipo(ipo);
+
+}
+
+
+void calchandles_ipocurve(IpoCurve *icu)
+{
+ BezTriple *bezt, *prev, *next;
+ int a;
+
+ a= icu->totvert;
+ if(a<2) return;
+
+ bezt= icu->bezt;
+ prev= 0;
+ next= bezt+1;
+
+ while(a--) {
+
+ if(bezt->vec[0][0]>bezt->vec[1][0]) bezt->vec[0][0]= bezt->vec[1][0];
+ if(bezt->vec[2][0]<bezt->vec[1][0]) bezt->vec[2][0]= bezt->vec[1][0];
+
+ calchandleNurb(bezt, prev, next, 1); /* 1==speciale autohandle */
+
+ prev= bezt;
+ if(a==1) {
+ next= 0;
+ }
+ else next++;
+
+ /* voor automatische ease in en out */
+ if(bezt->h1==HD_AUTO && bezt->h2==HD_AUTO) {
+ if(a==0 || a==icu->totvert-1) {
+ if(icu->extrap==IPO_HORIZ) {
+ bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
+ }
+ }
+ }
+
+ bezt++;
+ }
+}
+
+void testhandles_ipocurve(IpoCurve *icu)
+{
+ /* Te gebruiken als er iets aan de handles is veranderd.
+ * Loopt alle BezTriples af met de volgende regels:
+ * FASE 1: types veranderen?
+ * Autocalchandles: worden ligned als NOT(000 || 111)
+ * Vectorhandles worden 'niets' als (selected en andere niet)
+ * FASE 2: handles herberekenen
+ */
+ BezTriple *bezt;
+ int flag, a;
+
+ bezt= icu->bezt;
+ if(bezt==0) return;
+
+ a= icu->totvert;
+ while(a--) {
+ flag= 0;
+ if(bezt->f1 & 1) flag++;
+ if(bezt->f2 & 1) flag += 2;
+ if(bezt->f3 & 1) flag += 4;
+
+ if( !(flag==0 || flag==7) ) {
+ if(bezt->h1==HD_AUTO) { /* auto */
+ bezt->h1= HD_ALIGN;
+ }
+ if(bezt->h2==HD_AUTO) { /* auto */
+ bezt->h2= HD_ALIGN;
+ }
+
+ if(bezt->h1==HD_VECT) { /* vector */
+ if(flag < 4) bezt->h1= 0;
+ }
+ if(bezt->h2==HD_VECT) { /* vector */
+ if( flag > 3) bezt->h2= 0;
+ }
+ }
+ bezt++;
+ }
+
+ calchandles_ipocurve(icu);
+}
+
+
+void sort_time_ipocurve(IpoCurve *icu)
+{
+ BezTriple *bezt;
+ int a, ok= 1;
+
+ while(ok) {
+ ok= 0;
+
+ if(icu->bezt) {
+ bezt= icu->bezt;
+ a= icu->totvert;
+ while(a--) {
+ if(a>0) {
+ if( bezt->vec[1][0] > (bezt+1)->vec[1][0]) {
+ SWAP(BezTriple, *bezt, *(bezt+1));
+ ok= 1;
+ }
+ }
+ if(bezt->vec[0][0]>=bezt->vec[1][0] && bezt->vec[2][0]<=bezt->vec[1][0]) {
+ SWAP(float, bezt->vec[0][0], bezt->vec[2][0]);
+ SWAP(float, bezt->vec[0][1], bezt->vec[2][1]);
+ }
+ else {
+ if(bezt->vec[0][0]>bezt->vec[1][0]) bezt->vec[0][0]= bezt->vec[1][0];
+ if(bezt->vec[2][0]<bezt->vec[1][0]) bezt->vec[2][0]= bezt->vec[1][0];
+ }
+ bezt++;
+ }
+ }
+ else {
+
+ }
+ }
+}
+
+int test_time_ipocurve(IpoCurve *icu)
+{
+ BezTriple *bezt;
+ int a;
+
+ if(icu->bezt) {
+ bezt= icu->bezt;
+ a= icu->totvert-1;
+ while(a--) {
+ if( bezt->vec[1][0] > (bezt+1)->vec[1][0]) {
+ return 1;
+ }
+ bezt++;
+ }
+ }
+ else {
+
+ }
+
+ return 0;
+}
+
+void correct_bezpart(float *v1, float *v2, float *v3, float *v4)
+{
+ /* de totale lengte van de handles mag niet langer zijn
+ * dan de horizontale afstand tussen de punten (v1-v4)
+ */
+ float h1[2], h2[2], len1, len2, len, fac;
+
+ h1[0]= v1[0]-v2[0];
+ h1[1]= v1[1]-v2[1];
+ h2[0]= v4[0]-v3[0];
+ h2[1]= v4[1]-v3[1];
+
+ len= v4[0]- v1[0];
+ len1= (float)fabs(h1[0]);
+ len2= (float)fabs(h2[0]);
+
+ if(len1+len2==0.0) return;
+ if(len1+len2 > len) {
+ fac= len/(len1+len2);
+
+ v2[0]= (v1[0]-fac*h1[0]);
+ v2[1]= (v1[1]-fac*h1[1]);
+
+ v3[0]= (v4[0]-fac*h2[0]);
+ v3[1]= (v4[1]-fac*h2[1]);
+
+ }
+}
+
+/* *********************** ARITH *********************** */
+
+int findzero(float x, float q0, float q1, float q2, float q3, float *o)
+{
+ double c0, c1, c2, c3, a, b, c, p, q, d, t, phi;
+ int nr= 0;
+
+ c0= q0-x;
+ c1= 3*(q1-q0);
+ c2= 3*(q0-2*q1+q2);
+ c3= q3-q0+3*(q1-q2);
+
+ if(c3!=0.0) {
+ a= c2/c3;
+ b= c1/c3;
+ c= c0/c3;
+ a= a/3;
+
+ p= b/3-a*a;
+ q= (2*a*a*a-a*b+c)/2;
+ d= q*q+p*p*p;
+
+ if(d>0.0) {
+ t= sqrt(d);
+ o[0]= (float)(Sqrt3d(-q+t)+Sqrt3d(-q-t)-a);
+ if(o[0]>= SMALL && o[0]<=1.000001) return 1;
+ else return 0;
+ }
+ else if(d==0.0) {
+ t= Sqrt3d(-q);
+ o[0]= (float)(2*t-a);
+ if(o[0]>=SMALL && o[0]<=1.000001) nr++;
+ o[nr]= (float)(-t-a);
+ if(o[nr]>=SMALL && o[nr]<=1.000001) return nr+1;
+ else return nr;
+ }
+ else {
+ phi= acos(-q/sqrt(-(p*p*p)));
+ t= sqrt(-p);
+ p= cos(phi/3);
+ q= sqrt(3-3*p*p);
+ o[0]= (float)(2*t*p-a);
+ if(o[0]>=SMALL && o[0]<=1.000001) nr++;
+ o[nr]= (float)(-t*(p+q)-a);
+ if(o[nr]>=SMALL && o[nr]<=1.000001) nr++;
+ o[nr]= (float)(-t*(p-q)-a);
+ if(o[nr]>=SMALL && o[nr]<=1.000001) return nr+1;
+ else return nr;
+ }
+ }
+ else {
+ a=c2;
+ b=c1;
+ c=c0;
+
+ if(a!=0.0) {
+ p=b*b-4*a*c;
+ if(p>0) {
+ p= sqrt(p);
+ o[0]= (float)((-b-p)/(2*a));
+ if(o[0]>=SMALL && o[0]<=1.000001) nr++;
+ o[nr]= (float)((-b+p)/(2*a));
+ if(o[nr]>=SMALL && o[nr]<=1.000001) return nr+1;
+ else return nr;
+ }
+ else if(p==0) {
+ o[0]= (float)(-b/(2*a));
+ if(o[0]>=SMALL && o[0]<=1.000001) return 1;
+ else return 0;
+ }
+ }
+ else if(b!=0.0) {
+ o[0]= (float)(-c/b);
+ if(o[0]>=SMALL && o[0]<=1.000001) return 1;
+ else return 0;
+ }
+ else if(c==0.0) {
+ o[0]= 0.0;
+ return 1;
+ }
+ return 0;
+ }
+}
+
+void berekeny(float f1, float f2, float f3, float f4, float *o, int b)
+{
+ float t, c0, c1, c2, c3;
+ int a;
+
+ c0= f1;
+ c1= 3.0f*(f2 - f1);
+ c2= 3.0f*(f1 - 2.0f*f2 + f3);
+ c3= f4 - f1 + 3.0f*(f2-f3);
+
+ for(a=0; a<b; a++) {
+ t= o[a];
+ o[a]= c0+t*c1+t*t*c2+t*t*t*c3;
+ }
+}
+void berekenx(float *f, float *o, int b)
+{
+ float t, c0, c1, c2, c3;
+ int a;
+
+ c0= f[0];
+ c1= 3*(f[3]-f[0]);
+ c2= 3*(f[0]-2*f[3]+f[6]);
+ c3= f[9]-f[0]+3*(f[3]-f[6]);
+ for(a=0; a<b; a++) {
+ t= o[a];
+ o[a]= c0+t*c1+t*t*c2+t*t*t*c3;
+ }
+}
+
+float eval_icu(IpoCurve *icu, float ipotime)
+{
+ BezTriple *bezt, *prevbezt;
+ float v1[2], v2[2], v3[2], v4[2], opl[32], dx, fac;
+ float cycdx, cycdy, ofs, cycyofs, cvalue = 0.0;
+ int a, b;
+
+ cycyofs= 0.0;
+
+ if(icu->bezt) {
+ prevbezt= icu->bezt;
+ bezt= prevbezt+1;
+ a= icu->totvert-1;
+
+ /* cyclic? */
+ if(icu->extrap & IPO_CYCL) {
+ ofs= icu->bezt->vec[1][0];
+ cycdx= (icu->bezt+icu->totvert-1)->vec[1][0] - ofs;
+ cycdy= (icu->bezt+icu->totvert-1)->vec[1][1] - icu->bezt->vec[1][1];
+ if(cycdx!=0.0) {
+
+ if(icu->extrap & IPO_DIR) {
+ cycyofs= (float)floor((ipotime-ofs)/cycdx);
+ cycyofs*= cycdy;
+ }
+
+ ipotime= (float)(fmod(ipotime-ofs, cycdx)+ofs);
+ if(ipotime<ofs) ipotime+= cycdx;
+ }
+ }
+
+ /* uiteinden? */
+
+ if(prevbezt->vec[1][0]>=ipotime) {
+ if( (icu->extrap & IPO_DIR) && icu->ipo!=IPO_CONST) {
+ dx= prevbezt->vec[1][0]-ipotime;
+ fac= prevbezt->vec[1][0]-prevbezt->vec[0][0];
+ if(fac!=0.0) {
+ fac= (prevbezt->vec[1][1]-prevbezt->vec[0][1])/fac;
+ cvalue= prevbezt->vec[1][1]-fac*dx;
+ }
+ else cvalue= prevbezt->vec[1][1];
+ }
+ else cvalue= prevbezt->vec[1][1];
+
+ cvalue+= cycyofs;
+ }
+ else if( (prevbezt+a)->vec[1][0]<=ipotime) {
+ if( (icu->extrap & IPO_DIR) && icu->ipo!=IPO_CONST) {
+ prevbezt+= a;
+ dx= ipotime-prevbezt->vec[1][0];
+ fac= prevbezt->vec[2][0]-prevbezt->vec[1][0];
+
+ if(fac!=0) {
+ fac= (prevbezt->vec[2][1]-prevbezt->vec[1][1])/fac;
+ cvalue= prevbezt->vec[1][1]+fac*dx;
+ }
+ else cvalue= prevbezt->vec[1][1];
+ }
+ else cvalue= (prevbezt+a)->vec[1][1];
+
+ cvalue+= cycyofs;
+ }
+ else {
+ while(a--) {
+ if(prevbezt->vec[1][0]<=ipotime && bezt->vec[1][0]>=ipotime) {
+ if(icu->ipo==IPO_CONST) {
+ cvalue= prevbezt->vec[1][1]+cycyofs;
+ }
+ else if(icu->ipo==IPO_LIN) {
+ fac= bezt->vec[1][0]-prevbezt->vec[1][0];
+ if(fac==0) cvalue= cycyofs+prevbezt->vec[1][1];
+ else {
+ fac= (ipotime-prevbezt->vec[1][0])/fac;
+ cvalue= cycyofs+prevbezt->vec[1][1]+ fac*(bezt->vec[1][1]-prevbezt->vec[1][1]);
+ }
+ }
+ else {
+ v1[0]= prevbezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
+ v2[0]= prevbezt->vec[2][0];
+ v2[1]= prevbezt->vec[2][1];
+
+ v3[0]= bezt->vec[0][0];
+ v3[1]= bezt->vec[0][1];
+ v4[0]= bezt->vec[1][0];
+ v4[1]= bezt->vec[1][1];
+
+ correct_bezpart(v1, v2, v3, v4);
+
+ b= findzero(ipotime, v1[0], v2[0], v3[0], v4[0], opl);
+ if(b) {
+ berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1);
+ cvalue= opl[0]+cycyofs;
+ break;
+ }
+ }
+ }
+ prevbezt= bezt;
+ bezt++;
+ }
+ }
+ }
+
+ if(icu->ymin < icu->ymax) {
+ if(cvalue < icu->ymin) cvalue= icu->ymin;
+ else if(cvalue > icu->ymax) cvalue= icu->ymax;
+ }
+
+ return cvalue;
+}
+
+void calc_icu(IpoCurve *icu, float ctime)
+{
+ icu->curval= eval_icu(icu, ctime);
+}
+
+float calc_ipo_time(Ipo *ipo, float ctime)
+{
+
+ if(ipo && ipo->blocktype==ID_OB) {
+ IpoCurve *icu= ipo->curve.first;
+
+ while(icu) {
+ if (icu->adrcode==OB_TIME) {
+ calc_icu(icu, ctime);
+ return 10.0f*icu->curval;
+ }
+ icu= icu->next;
+ }
+ }
+
+ return ctime;
+}
+
+void calc_ipo(Ipo *ipo, float ctime)
+{
+ IpoCurve *icu;
+
+ icu= ipo->curve.first;
+ while(icu) {
+
+ if( (icu->flag & IPO_LOCK)==0) calc_icu(icu, ctime);
+
+ icu= icu->next;
+ }
+}
+
+/* ************************************** */
+/* DO THE IPO! */
+/* ************************************** */
+
+void write_ipo_poin(void *poin, int type, float val)
+{
+
+ switch(type) {
+ case IPO_FLOAT:
+ *( (float *)poin)= val;
+ break;
+ case IPO_FLOAT_DEGR:
+ *( (float *)poin)= (float)(val*M_PI_2/9.0);
+ break;
+ case IPO_INT:
+ case IPO_INT_BIT:
+ case IPO_LONG:
+ *( (int *)poin)= (int)val;
+ break;
+ case IPO_SHORT:
+ case IPO_SHORT_BIT:
+ *( (short *)poin)= (short)val;
+ break;
+ case IPO_CHAR:
+ case IPO_CHAR_BIT:
+ *( (char *)poin)= (char)val;
+ break;
+ }
+}
+
+float read_ipo_poin(void *poin, int type)
+{
+ float val = 0.0;
+
+ switch(type) {
+ case IPO_FLOAT:
+ val= *( (float *)poin);
+ break;
+ case IPO_FLOAT_DEGR:
+ val= *( (float *)poin);
+ val = (float)(val/(M_PI_2/9.0));
+ break;
+ case IPO_INT:
+ case IPO_INT_BIT:
+ case IPO_LONG:
+ val= (float)(*( (int *)poin));
+ break;
+ case IPO_SHORT:
+ case IPO_SHORT_BIT:
+ val= *( (short *)poin);
+ break;
+ case IPO_CHAR:
+ case IPO_CHAR_BIT:
+ val= *( (char *)poin);
+ break;
+ }
+ return val;
+}
+
+void *give_mtex_poin(MTex *mtex, int adrcode )
+{
+ void *poin=0;
+
+ switch(adrcode) {
+ case MAP_OFS_X:
+ poin= &(mtex->ofs[0]); break;
+ case MAP_OFS_Y:
+ poin= &(mtex->ofs[1]); break;
+ case MAP_OFS_Z:
+ poin= &(mtex->ofs[2]); break;
+ case MAP_SIZE_X:
+ poin= &(mtex->size[0]); break;
+ case MAP_SIZE_Y:
+ poin= &(mtex->size[1]); break;
+ case MAP_SIZE_Z:
+ poin= &(mtex->size[2]); break;
+ case MAP_R:
+ poin= &(mtex->r); break;
+ case MAP_G:
+ poin= &(mtex->g); break;
+ case MAP_B:
+ poin= &(mtex->b); break;
+ case MAP_DVAR:
+ poin= &(mtex->def_var); break;
+ case MAP_COLF:
+ poin= &(mtex->colfac); break;
+ case MAP_NORF:
+ poin= &(mtex->norfac); break;
+ case MAP_VARF:
+ poin= &(mtex->varfac); break;
+ }
+
+ return poin;
+}
+
+/* GS reads the memory pointed at in a specific ordering. There are,
+ * however two definitions for it. I have jotted them down here, both,
+ * but I think the first one is actually used. The thing is that
+ * big-endian systems might read this the wrong way round. OTOH, we
+ * constructed the IDs that are read out with this macro explicitly as
+ * well. I expect we'll sort it out soon... */
+
+/* from blendef: */
+#define GS(a) (*((short *)(a)))
+
+/* from misc_util: flip the bytes from x */
+/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
+
+void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
+{
+ void *poin= 0;
+ Object *ob;
+ Material *ma;
+ MTex *mtex;
+ Ika *ika= 0;
+ Lamp *la;
+ Sequence *seq;
+ World *wo;
+ bAction *act;
+ bActionChannel *achan;
+ bPoseChannel *pchan;
+
+ *type= IPO_FLOAT;
+
+
+ if( GS(id->name)==ID_OB) {
+
+ ob= (Object *)id;
+
+ if(ob->type==OB_IKA) ika= ob->data;
+
+ switch(icu->adrcode) {
+ case OB_LOC_X:
+ poin= &(ob->loc[0]); break;
+ case OB_LOC_Y:
+ poin= &(ob->loc[1]); break;
+ case OB_LOC_Z:
+ poin= &(ob->loc[2]); break;
+ case OB_DLOC_X:
+ poin= &(ob->dloc[0]); break;
+ case OB_DLOC_Y:
+ poin= &(ob->dloc[1]); break;
+ case OB_DLOC_Z:
+ poin= &(ob->dloc[2]); break;
+
+ case OB_ROT_X:
+ poin= &(ob->rot[0]); *type= IPO_FLOAT_DEGR; break;
+ case OB_ROT_Y:
+ poin= &(ob->rot[1]); *type= IPO_FLOAT_DEGR; break;
+ case OB_ROT_Z:
+ poin= &(ob->rot[2]); *type= IPO_FLOAT_DEGR; break;
+ case OB_DROT_X:
+ poin= &(ob->drot[0]); *type= IPO_FLOAT_DEGR; break;
+ case OB_DROT_Y:
+ poin= &(ob->drot[1]); *type= IPO_FLOAT_DEGR; break;
+ case OB_DROT_Z:
+ poin= &(ob->drot[2]); *type= IPO_FLOAT_DEGR; break;
+
+ case OB_SIZE_X:
+ poin= &(ob->size[0]); break;
+ case OB_SIZE_Y:
+ poin= &(ob->size[1]); break;
+ case OB_SIZE_Z:
+ poin= &(ob->size[2]); break;
+ case OB_DSIZE_X:
+ poin= &(ob->dsize[0]); break;
+ case OB_DSIZE_Y:
+ poin= &(ob->dsize[1]); break;
+ case OB_DSIZE_Z:
+ poin= &(ob->dsize[2]); break;
+
+ case OB_LAY:
+ poin= &(ob->lay); *type= IPO_INT_BIT; break;
+
+ case OB_EFF_X: /* OB_COL_R */
+ if(ika) poin= &(ika->effg[0]);
+ else poin= &(ob->col[0]);
+ break;
+ case OB_EFF_Y: /* OB_COL_G */
+ if(ika) poin= &(ika->effg[1]);
+ else poin= &(ob->col[1]);
+ break;
+ case OB_EFF_Z: /* OB_COL_B */
+ if(ika) poin= &(ika->effg[2]);
+ else poin= &(ob->col[2]);
+ break;
+ case OB_COL_A:
+ poin= &(ob->col[3]);
+ break;
+ }
+ }
+ else if (GS(id->name)==ID_AC){
+ act= (bAction *)id;
+ achan = act->achan;
+ pchan = act->pchan;
+ if (!pchan || !achan)
+ return NULL;
+ switch (icu->adrcode){
+ case AC_QUAT_W:
+ poin= &(pchan->quat[0]); break;
+ case AC_QUAT_X:
+ poin= &(pchan->quat[1]); break;
+ case AC_QUAT_Y:
+ poin= &(pchan->quat[2]); break;
+ case AC_QUAT_Z:
+ poin= &(pchan->quat[3]); break;
+ case AC_LOC_X:
+ poin= &(pchan->loc[0]); break;
+ case AC_LOC_Y:
+ poin= &(pchan->loc[1]); break;
+ case AC_LOC_Z:
+ poin= &(pchan->loc[2]); break;
+ case AC_SIZE_X:
+ poin= &(pchan->size[0]); break;
+ case AC_SIZE_Y:
+ poin= &(pchan->size[1]); break;
+ case AC_SIZE_Z:
+ poin= &(pchan->size[2]); break;
+ };
+ }
+
+ else if( GS(id->name)==ID_MA) {
+
+ ma= (Material *)id;
+
+ switch(icu->adrcode) {
+ case MA_COL_R:
+ poin= &(ma->r); break;
+ case MA_COL_G:
+ poin= &(ma->g); break;
+ case MA_COL_B:
+ poin= &(ma->b); break;
+ case MA_SPEC_R:
+ poin= &(ma->specr); break;
+ case MA_SPEC_G:
+ poin= &(ma->specg); break;
+ case MA_SPEC_B:
+ poin= &(ma->specb); break;
+ case MA_MIR_R:
+ poin= &(ma->mirr); break;
+ case MA_MIR_G:
+ poin= &(ma->mirg); break;
+ case MA_MIR_B:
+ poin= &(ma->mirb); break;
+ case MA_REF:
+ poin= &(ma->ref); break;
+ case MA_ALPHA:
+ poin= &(ma->alpha); break;
+ case MA_EMIT:
+ poin= &(ma->emit); break;
+ case MA_AMB:
+ poin= &(ma->amb); break;
+ case MA_SPEC:
+ poin= &(ma->spec); break;
+ case MA_HARD:
+ poin= &(ma->har); *type= IPO_SHORT; break;
+ case MA_SPTR:
+ poin= &(ma->spectra); break;
+ case MA_ANG:
+ poin= &(ma->ang); break;
+ case MA_MODE:
+ poin= &(ma->mode); *type= IPO_INT_BIT; break;
+ case MA_HASIZE:
+ poin= &(ma->hasize); break;
+ }
+
+ if(poin==0) {
+ mtex= 0;
+ if(icu->adrcode & MA_MAP1) mtex= ma->mtex[0];
+ else if(icu->adrcode & MA_MAP2) mtex= ma->mtex[1];
+ else if(icu->adrcode & MA_MAP3) mtex= ma->mtex[2];
+ else if(icu->adrcode & MA_MAP4) mtex= ma->mtex[3];
+ else if(icu->adrcode & MA_MAP5) mtex= ma->mtex[4];
+ else if(icu->adrcode & MA_MAP6) mtex= ma->mtex[5];
+ else if(icu->adrcode & MA_MAP7) mtex= ma->mtex[6];
+ else if(icu->adrcode & MA_MAP8) mtex= ma->mtex[7];
+
+ if(mtex) {
+ poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
+ }
+ }
+ }
+ else if( GS(id->name)==ID_SEQ) {
+ seq= (Sequence *)id;
+
+ switch(icu->adrcode) {
+ case SEQ_FAC1:
+ poin= &(seq->facf0); break;
+ }
+ }
+ else if( GS(id->name)==ID_CU) {
+
+ poin= &(icu->curval);
+
+ }
+ else if( GS(id->name)==ID_KE) {
+
+ poin= &(icu->curval);
+
+ }
+ else if(GS(id->name)==ID_WO) {
+
+ wo= (World *)id;
+
+ switch(icu->adrcode) {
+ case WO_HOR_R:
+ poin= &(wo->horr); break;
+ case WO_HOR_G:
+ poin= &(wo->horg); break;
+ case WO_HOR_B:
+ poin= &(wo->horb); break;
+ case WO_ZEN_R:
+ poin= &(wo->zenr); break;
+ case WO_ZEN_G:
+ poin= &(wo->zeng); break;
+ case WO_ZEN_B:
+ poin= &(wo->zenb); break;
+
+ case WO_EXPOS:
+ poin= &(wo->exposure); break;
+
+ case WO_MISI:
+ poin= &(wo->misi); break;
+ case WO_MISTDI:
+ poin= &(wo->mistdist); break;
+ case WO_MISTSTA:
+ poin= &(wo->miststa); break;
+ case WO_MISTHI:
+ poin= &(wo->misthi); break;
+
+ case WO_STAR_R:
+ poin= &(wo->starr); break;
+ case WO_STAR_G:
+ poin= &(wo->starg); break;
+ case WO_STAR_B:
+ poin= &(wo->starb); break;
+
+ case WO_STARDIST:
+ poin= &(wo->stardist); break;
+ case WO_STARSIZE:
+ poin= &(wo->starsize); break;
+ }
+
+ if(poin==0) {
+ mtex= 0;
+ if(icu->adrcode & MA_MAP1) mtex= wo->mtex[0];
+ else if(icu->adrcode & MA_MAP2) mtex= wo->mtex[1];
+ else if(icu->adrcode & MA_MAP3) mtex= wo->mtex[2];
+ else if(icu->adrcode & MA_MAP4) mtex= wo->mtex[3];
+ else if(icu->adrcode & MA_MAP5) mtex= wo->mtex[4];
+ else if(icu->adrcode & MA_MAP6) mtex= wo->mtex[5];
+ else if(icu->adrcode & MA_MAP7) mtex= wo->mtex[6];
+ else if(icu->adrcode & MA_MAP8) mtex= wo->mtex[7];
+
+ if(mtex) {
+ poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
+ }
+ }
+ }
+ else if( GS(id->name)==ID_LA) {
+
+ la= (Lamp *)id;
+
+ switch(icu->adrcode) {
+ case LA_ENERGY:
+ poin= &(la->energy); break;
+ case LA_COL_R:
+ poin= &(la->r); break;
+ case LA_COL_G:
+ poin= &(la->g); break;
+ case LA_COL_B:
+ poin= &(la->b); break;
+ case LA_DIST:
+ poin= &(la->dist); break;
+ case LA_SPOTSI:
+ poin= &(la->spotsize); break;
+ case LA_SPOTBL:
+ poin= &(la->spotblend); break;
+ case LA_QUAD1:
+ poin= &(la->att1); break;
+ case LA_QUAD2:
+ poin= &(la->att2); break;
+ case LA_HALOINT:
+ poin= &(la->haint); break;
+ }
+
+ if(poin==0) {
+ mtex= 0;
+ if(icu->adrcode & MA_MAP1) mtex= la->mtex[0];
+ else if(icu->adrcode & MA_MAP2) mtex= la->mtex[1];
+ else if(icu->adrcode & MA_MAP3) mtex= la->mtex[2];
+ else if(icu->adrcode & MA_MAP4) mtex= la->mtex[3];
+ else if(icu->adrcode & MA_MAP5) mtex= la->mtex[4];
+ else if(icu->adrcode & MA_MAP6) mtex= la->mtex[5];
+ else if(icu->adrcode & MA_MAP7) mtex= la->mtex[6];
+ else if(icu->adrcode & MA_MAP8) mtex= la->mtex[7];
+
+ if(mtex) {
+ poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
+ }
+ }
+ }
+ else if(GS(id->name)==ID_CA) {
+ Camera *ca= (Camera *)id;
+
+ switch(icu->adrcode) {
+ case CAM_LENS:
+ poin= &(ca->lens); break;
+ case CAM_STA:
+ poin= &(ca->clipsta); break;
+ case CAM_END:
+ poin= &(ca->clipend); break;
+ }
+ }
+ else if(GS(id->name)==ID_SO) {
+ bSound *snd= (bSound *)id;
+
+ switch(icu->adrcode) {
+ case SND_VOLUME:
+ poin= &(snd->volume); break;
+ case SND_PITCH:
+ poin= &(snd->pitch); break;
+ case SND_PANNING:
+ poin= &(snd->panning); break;
+ case SND_ATTEN:
+ poin= &(snd->attenuation); break;
+ }
+ }
+
+ return poin;
+}
+
+void set_icu_vars(IpoCurve *icu)
+{
+
+ icu->ymin= icu->ymax= 0.0;
+ icu->ipo= IPO_BEZ;
+
+ if(icu->blocktype==ID_OB) {
+
+ if(icu->adrcode==OB_LAY) {
+ icu->ipo= IPO_CONST;
+ icu->vartype= IPO_BITS;
+ }
+
+ }
+ else if(icu->blocktype==ID_MA) {
+
+ if(icu->adrcode < MA_MAP1) {
+ switch(icu->adrcode) {
+ case MA_HASIZE:
+ icu->ymax= 10000.0; break;
+ case MA_HARD:
+ icu->ymax= 128.0; break;
+ case MA_SPEC:
+ icu->ymax= 2.0; break;
+ case MA_MODE:
+ icu->ipo= IPO_CONST;
+ icu->vartype= IPO_BITS;
+ break;
+
+ default:
+ icu->ymax= 1.0;
+ break;
+ }
+ }
+ else {
+ switch(icu->adrcode & (MA_MAP1-1)) {
+ case MAP_OFS_X:
+ case MAP_OFS_Y:
+ case MAP_OFS_Z:
+ case MAP_SIZE_X:
+ case MAP_SIZE_Y:
+ case MAP_SIZE_Z:
+ icu->ymax= 1000.0;
+ icu->ymin= -1000.0;
+
+ break;
+ case MAP_R:
+ case MAP_G:
+ case MAP_B:
+ case MAP_DVAR:
+ case MAP_COLF:
+ case MAP_VARF:
+ icu->ymax= 1.0;
+ break;
+ case MAP_NORF:
+ icu->ymax= 5.0;
+ break;
+ }
+ }
+ }
+ else if(icu->blocktype==ID_SEQ) {
+
+ icu->ymax= 1.0;
+
+ }
+ else if(icu->blocktype==ID_CU) {
+
+ icu->ymax= 1.0;
+
+ }
+ else if(icu->blocktype==ID_WO) {
+
+ if(icu->adrcode < MA_MAP1) {
+ switch(icu->adrcode) {
+ case WO_EXPOS:
+ icu->ymax= 5.0; break;
+ case WO_MISTDI:
+ case WO_MISTSTA:
+ case WO_MISTHI:
+ case WO_STARDIST:
+ case WO_STARSIZE:
+ break;
+
+ default:
+ icu->ymax= 1.0;
+ break;
+ }
+ }
+ else {
+ switch(icu->adrcode & (MA_MAP1-1)) {
+ case MAP_OFS_X:
+ case MAP_OFS_Y:
+ case MAP_OFS_Z:
+ case MAP_SIZE_X:
+ case MAP_SIZE_Y:
+ case MAP_SIZE_Z:
+ icu->ymax= 100.0;
+ icu->ymin= -100.0;
+
+ break;
+ case MAP_R:
+ case MAP_G:
+ case MAP_B:
+ case MAP_DVAR:
+ case MAP_COLF:
+ case MAP_NORF:
+ case MAP_VARF:
+ icu->ymax= 1.0;
+ }
+ }
+ }
+ else if(icu->blocktype==ID_LA) {
+ if(icu->adrcode < MA_MAP1) {
+ switch(icu->adrcode) {
+ case LA_ENERGY:
+ case LA_DIST:
+ break;
+
+ case LA_COL_R:
+ case LA_COL_G:
+ case LA_COL_B:
+ case LA_SPOTBL:
+ case LA_QUAD1:
+ case LA_QUAD2:
+ icu->ymax= 1.0; break;
+ case LA_SPOTSI:
+ icu->ymax= 180.0; break;
+ case LA_HALOINT:
+ icu->ymax= 5.0; break;
+ }
+ }
+ else {
+ switch(icu->adrcode & (MA_MAP1-1)) {
+ case MAP_OFS_X:
+ case MAP_OFS_Y:
+ case MAP_OFS_Z:
+ case MAP_SIZE_X:
+ case MAP_SIZE_Y:
+ case MAP_SIZE_Z:
+ icu->ymax= 100.0;
+ icu->ymin= -100.0;
+ break;
+ case MAP_R:
+ case MAP_G:
+ case MAP_B:
+ case MAP_DVAR:
+ case MAP_COLF:
+ case MAP_NORF:
+ case MAP_VARF:
+ icu->ymax= 1.0;
+ }
+ }
+ }
+ else if(icu->blocktype==ID_CA) {
+
+ switch(icu->adrcode) {
+ case CAM_LENS:
+ icu->ymin= 5.0;
+ icu->ymax= 1000.0; break;
+ case CAM_STA:
+ icu->ymin= 0.001f;
+ break;
+ case CAM_END:
+ icu->ymin= 0.1f;
+ }
+ }
+ else if(icu->blocktype==ID_SO) {
+
+ switch(icu->adrcode) {
+ case SND_VOLUME:
+ icu->ymin= 0.0;
+ icu->ymax= 1.0;
+ break;
+ case SND_PITCH:
+ icu->ymin= -12.0;
+ icu->ymin= 12.0;
+ break;
+ case SND_PANNING:
+ icu->ymin= 0.0;
+ icu->ymax= 1.0;
+ break;
+ case SND_ATTEN:
+ icu->ymin= 0.0;
+ icu->ymin= 1.0;
+ break;
+ }
+ }
+}
+
+
+void execute_ipo(ID *id, Ipo *ipo)
+{
+ IpoCurve *icu;
+ void *poin;
+ int type;
+
+ if(ipo==0) return;
+
+ icu= ipo->curve.first;
+ while(icu) {
+ poin= get_ipo_poin(id, icu, &type);
+ if(poin) write_ipo_poin(poin, type, icu->curval);
+ icu= icu->next;
+ }
+}
+
+/* exception: it does calc for objects...
+ * now find out why this routine was used anyway!
+ */
+void do_ipo_nocalc(Ipo *ipo)
+{
+ Object *ob;
+ Material *ma;
+ World *wo;
+ Lamp *la;
+ Camera *ca;
+ bSound *snd;
+
+ if(ipo==0) return;
+
+ switch(ipo->blocktype) {
+ case ID_OB:
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->ipo==ipo) {
+ do_ob_ipo(ob);
+ /* execute_ipo((ID *)ob, ipo); */
+ }
+ ob= ob->id.next;
+ }
+ break;
+ case ID_MA:
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->ipo==ipo) execute_ipo((ID *)ma, ipo);
+ ma= ma->id.next;
+ }
+ break;
+ case ID_WO:
+ wo= G.main->world.first;
+ while(wo) {
+ if(wo->ipo==ipo) execute_ipo((ID *)wo, ipo);
+ wo= wo->id.next;
+ }
+ break;
+ case ID_LA:
+ la= G.main->lamp.first;
+ while(la) {
+ if(la->ipo==ipo) execute_ipo((ID *)la, ipo);
+ la= la->id.next;
+ }
+ break;
+ case ID_CA:
+ ca= G.main->camera.first;
+ while(ca) {
+ if(ca->ipo==ipo) execute_ipo((ID *)ca, ipo);
+ ca= ca->id.next;
+ }
+ break;
+ case ID_SO:
+ snd= G.main->sound.first;
+ while(snd) {
+ if(snd->ipo==ipo) execute_ipo((ID *)snd, ipo);
+ snd= snd->id.next;
+ }
+ break;
+ }
+}
+
+void do_ipo(Ipo *ipo)
+{
+ if(ipo) {
+ float ctime= frame_to_float(G.scene->r.cfra);
+ calc_ipo(ipo, ctime);
+
+ do_ipo_nocalc(ipo);
+ }
+}
+
+
+
+void do_mat_ipo(Material *ma)
+{
+ float ctime;
+
+ if(ma==0 || ma->ipo==0) return;
+
+ ctime= frame_to_float(G.scene->r.cfra);
+ /* if(ob->ipoflag & OB_OFFS_OB) ctime-= ob->sf; */
+
+ calc_ipo(ma->ipo, ctime);
+
+ execute_ipo((ID *)ma, ma->ipo);
+}
+
+void do_ob_ipo(Object *ob)
+{
+ float ctime;
+ unsigned int lay;
+
+ if(ob->ipo==0) return;
+
+ /* hier NIET ob->ctime zetten: bijv bij parent in onzichtb. layer */
+
+ ctime= bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0);
+
+ calc_ipo(ob->ipo, ctime);
+
+ /* Patch: de localview onthouden */
+ lay= ob->lay & 0xFF000000;
+
+ execute_ipo((ID *)ob, ob->ipo);
+
+ ob->lay |= lay;
+ if(ob->id.name[2]=='S' && ob->id.name[3]=='C' && ob->id.name[4]=='E') {
+ if(strcmp(G.scene->id.name+2, ob->id.name+6)==0) {
+ G.scene->lay= ob->lay;
+ copy_view3d_lock(0);
+ /* hier geen REDRAW: gaat rondzingen! */
+ }
+ }
+}
+
+void do_seq_ipo(Sequence *seq)
+{
+ float ctime, div;
+
+ /* seq_ipo gaat iets anders: beide fields direkt berekenen */
+
+ if(seq->ipo) {
+ ctime= frame_to_float(G.scene->r.cfra - seq->startdisp);
+ div= (seq->enddisp - seq->startdisp)/100.0f;
+ if(div==0) return;
+
+ /* tweede field */
+ calc_ipo(seq->ipo, (ctime+0.5f)/div);
+ execute_ipo((ID *)seq, seq->ipo);
+ seq->facf1= seq->facf0;
+
+ /* eerste field */
+ calc_ipo(seq->ipo, ctime/div);
+ execute_ipo((ID *)seq, seq->ipo);
+
+ }
+ else seq->facf1= seq->facf0= 1.0f;
+}
+
+int has_ipo_code(Ipo *ipo, int code)
+{
+ IpoCurve *icu;
+
+ if(ipo==0) return 0;
+
+ icu= ipo->curve.first;
+ while(icu) {
+
+ if(icu->adrcode==code) return 1;
+
+ icu= icu->next;
+ }
+ return 0;
+}
+
+void do_all_ipos()
+{
+ Base *base;
+ Material *ma;
+ World *wo;
+ Ipo *ipo;
+ Lamp *la;
+ Camera *ca;
+ bSound *snd;
+ float ctime;
+ int set;
+
+ ctime= frame_to_float(G.scene->r.cfra);
+
+ ipo= G.main->ipo.first;
+ while(ipo) {
+ if(ipo->id.us && ipo->blocktype!=ID_OB) {
+ calc_ipo(ipo, ctime);
+ }
+ ipo= ipo->id.next;
+ }
+
+ /* NEW: current scene ob ipo's */
+ base= G.scene->base.first;
+ set= 0;
+ while(base) {
+
+ /* Do object ipos */
+ do_constraint_channels(&base->object->constraints, &base->object->constraintChannels, ctime);
+
+ if(base->object->ipo) {
+ /* per object ipo ook de calc_ipo doen: ivm mogelijke timeoffs */
+ do_ob_ipo(base->object);
+ if(base->object->type==OB_MBALL) where_is_object(base->object);
+ }
+ base= base->next;
+
+ if(base==0 && set==0 && G.scene->set) {
+ set= 1;
+ base= G.scene->set->base.first;
+ }
+ }
+
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->ipo) execute_ipo((ID *)ma, ma->ipo);
+ ma= ma->id.next;
+ }
+
+ wo= G.main->world.first;
+ while(wo) {
+ if(wo->ipo) execute_ipo((ID *)wo, wo->ipo);
+ wo= wo->id.next;
+ }
+
+ la= G.main->lamp.first;
+ while(la) {
+ if(la->ipo) execute_ipo((ID *)la, la->ipo);
+ la= la->id.next;
+ }
+
+ ca= G.main->camera.first;
+ while(ca) {
+ if(ca->ipo) execute_ipo((ID *)ca, ca->ipo);
+ ca= ca->id.next;
+ }
+
+ snd= G.main->sound.first;
+ while(snd) {
+ if(snd->ipo) execute_ipo((ID *)snd, snd->ipo);
+ snd= snd->id.next;
+ }
+
+ /* voor het geval dat... LET OP: 2x */
+ base= G.scene->base.first;
+ while(base) {
+
+ /* alleen layer updaten als ipo */
+ if( has_ipo_code(base->object->ipo, OB_LAY) ) {
+ base->lay= base->object->lay;
+ }
+
+ base= base->next;
+ }
+
+ /* voor het geval dat...*/
+ if(G.scene->set) {
+ base= G.scene->set->base.first;
+ while(base) {
+
+ /* alleen layer updaten als ipo */
+ if( has_ipo_code(base->object->ipo, OB_LAY) ) {
+ base->lay= base->object->lay;
+ }
+
+ base= base->next;
+ }
+ }
+}
+
+
+int calc_ipo_spec(Ipo *ipo, int adrcode, float *ctime)
+{
+ IpoCurve *icu;
+
+ if(ipo==0) return 0;
+
+ icu= ipo->curve.first;
+ while(icu) {
+ if(icu->adrcode == adrcode) {
+ if(icu->flag & IPO_LOCK);
+ else calc_icu(icu, *ctime);
+
+ *ctime= icu->curval;
+ return 1;
+ }
+ icu= icu->next;
+ }
+
+ return 0;
+}
+
+
+/* ************************** */
+
+void clear_delta_obipo(Ipo *ipo)
+{
+ Object *ob;
+
+ if(ipo==0) return;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->id.lib==0) {
+ if(ob->ipo==ipo) {
+ memset(&ob->dloc, 0, 12);
+ memset(&ob->drot, 0, 12);
+ memset(&ob->dsize, 0, 12);
+ }
+ }
+ ob= ob->id.next;
+ }
+}
+
+void add_to_cfra_elem(ListBase *lb, BezTriple *bezt)
+{
+ CfraElem *ce, *cen;
+
+ ce= lb->first;
+ while(ce) {
+
+ if( ce->cfra==bezt->vec[1][0] ) {
+ /* doen ivm dubbele keys */
+ if(bezt->f2 & 1) ce->sel= bezt->f2;
+ return;
+ }
+ else if(ce->cfra > bezt->vec[1][0]) break;
+
+ ce= ce->next;
+ }
+
+ cen= MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem");
+ if(ce) BLI_insertlinkbefore(lb, ce, cen);
+ else BLI_addtail(lb, cen);
+
+ cen->cfra= bezt->vec[1][0];
+ cen->sel= bezt->f2;
+}
+
+
+
+void make_cfra_list(Ipo *ipo, ListBase *elems)
+{
+ IpoCurve *icu;
+ CfraElem *ce;
+ BezTriple *bezt;
+ int a;
+
+ if(ipo->blocktype==ID_OB) {
+ icu= ipo->curve.first;
+ while(icu) {
+ if(icu->flag & IPO_VISIBLE) {
+ switch(icu->adrcode) {
+ case OB_DLOC_X:
+ case OB_DLOC_Y:
+ case OB_DLOC_Z:
+ case OB_DROT_X:
+ case OB_DROT_Y:
+ case OB_DROT_Z:
+ case OB_DSIZE_X:
+ case OB_DSIZE_Y:
+ case OB_DSIZE_Z:
+
+ case OB_LOC_X:
+ case OB_LOC_Y:
+ case OB_LOC_Z:
+ case OB_ROT_X:
+ case OB_ROT_Y:
+ case OB_ROT_Z:
+ case OB_SIZE_X:
+ case OB_SIZE_Y:
+ case OB_SIZE_Z:
+ bezt= icu->bezt;
+ if(bezt) {
+ a= icu->totvert;
+ while(a--) {
+ add_to_cfra_elem(elems, bezt);
+ bezt++;
+ }
+ }
+ break;
+ }
+ }
+ icu= icu->next;
+ }
+ }
+ if(ipo->showkey==0) {
+ /* alle keys deselecteren */
+ ce= elems->first;
+ while(ce) {
+ ce->sel= 0;
+ ce= ce->next;
+ }
+ }
+}
+
+/* *********************** INTERFACE FOR KETSJI ********** */
+
+
+int IPO_GetChannels(Ipo *ipo, IPO_Channel *channels)
+{
+ /* channels is max 32 items, allocated by calling function */
+
+ IpoCurve *icu;
+ int total=0;
+
+ if(ipo==NULL) return 0;
+
+ icu= ipo->curve.first;
+ while(icu) {
+
+ channels[total]= icu->adrcode;
+ total++;
+ if(total>31) break;
+
+ icu= icu->next;
+ }
+
+ return total;
+}
+
+
+
+/* Get the float value for channel 'channel' at time 'ctime' */
+
+float IPO_GetFloatValue(Ipo *ipo, IPO_Channel channel, float ctime)
+{
+ if(ipo==NULL) return 0;
+
+ calc_ipo_spec(ipo, channel, &ctime);
+
+ if (OB_ROT_X <= channel && channel <= OB_DROT_Z) {
+ ctime *= (float)(M_PI_2/9.0);
+ }
+
+ return ctime;
+}
+
+
+void test_ipo_get()
+{
+ Object *ob;
+ int tot;
+ IPO_Channel chan[32];
+
+ ob = (G.scene->basact ? G.scene->basact->object : 0);
+
+ if(ob==NULL) return;
+ if(ob->ipo==NULL) return;
+
+ tot= IPO_GetChannels(ob->ipo, chan);
+ printf("tot %d \n", tot);
+
+ while(tot--) {
+ printf("var1 %d \n", chan[tot]);
+ }
+
+ printf("var1 %f \n", IPO_GetFloatValue(ob->ipo, chan[0], 10.0));
+}
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
new file mode 100644
index 00000000000..d3ea2da204b
--- /dev/null
+++ b/source/blender/blenkernel/intern/key.c
@@ -0,0 +1,1212 @@
+
+/* key.c MIXED MODEL
+ *
+ * mei 95
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_key_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+
+#include "BLI_blenlib.h"
+#include "BKE_utildefines.h"
+#include "BKE_bad_level_calls.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_library.h"
+#include "BKE_blender.h"
+#include "BKE_curve.h"
+#include "BKE_object.h"
+#include "BKE_mesh.h"
+#include "BKE_key.h"
+#include "BKE_ipo.h"
+#include "BKE_lattice.h"
+
+
+#define KEY_BPOINT 1
+#define KEY_BEZTRIPLE 2
+
+int slurph_opt= 1;
+
+
+void free_key(Key *key)
+{
+ KeyBlock *kb;
+
+ if(key->ipo) key->ipo->id.us--;
+
+
+ while( (kb= key->block.first) ) {
+
+ if(kb->data) MEM_freeN(kb->data);
+
+ BLI_remlink(&key->block, kb);
+ MEM_freeN(kb);
+ }
+
+}
+
+/* GS reads the memory pointed at in a specific ordering. There are,
+ * however two definitions for it. I have jotted them down here, both,
+ * but I think the first one is actually used. The thing is that
+ * big-endian systems might read this the wrong way round. OTOH, we
+ * constructed the IDs that are read out with this macro explicitly as
+ * well. I expect we'll sort it out soon... */
+
+/* from blendef: */
+#define GS(a) (*((short *)(a)))
+
+/* from misc_util: flip the bytes from x */
+/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
+
+Key *add_key(ID *id) /* algemeen */
+{
+ Key *key;
+ char *el;
+
+ key= alloc_libblock(&G.main->key, ID_KE, "Key");
+
+ key->type= KEY_NORMAL;
+ key->from= id;
+
+ if( GS(id->name)==ID_ME) {
+ el= key->elemstr;
+
+ el[0]= 3;
+ el[1]= IPO_FLOAT;
+ el[2]= 0;
+
+ key->elemsize= 12;
+ }
+ else if( GS(id->name)==ID_LT) {
+ el= key->elemstr;
+
+ el[0]= 3;
+ el[1]= IPO_FLOAT;
+ el[2]= 0;
+
+ key->elemsize= 12;
+ }
+ else if( GS(id->name)==ID_CU) {
+ el= key->elemstr;
+
+ el[0]= 4;
+ el[1]= IPO_BPOINT;
+ el[2]= 0;
+
+ key->elemsize= 16;
+ }
+
+ return key;
+}
+
+Key *copy_key(Key *key)
+{
+ Key *keyn;
+ KeyBlock *kbn, *kb;
+
+ if(key==0) return 0;
+
+ keyn= copy_libblock(key);
+
+ keyn->ipo= copy_ipo(key->ipo);
+
+ duplicatelist(&keyn->block, &key->block);
+
+ kb= key->block.first;
+ kbn= keyn->block.first;
+ while(kbn) {
+
+ if(kbn->data) kbn->data= MEM_dupallocN(kbn->data);
+ if( kb==key->refkey ) keyn->refkey= kbn;
+
+ kbn= kbn->next;
+ kb= kb->next;
+ }
+
+ return keyn;
+}
+
+void make_local_key(Key *key)
+{
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+ if(key==0) return;
+
+ key->id.lib= 0;
+ new_id(0, (ID *)key, 0);
+ make_local_ipo(key->ipo);
+}
+
+
+void sort_keys(Key *key)
+{
+ KeyBlock *kb;
+ int doit=1;
+
+ while(doit) {
+ doit= 0;
+
+ kb= key->block.first;
+ while(kb) {
+ if(kb->next) {
+ if(kb->pos > kb->next->pos) {
+ BLI_remlink(&key->block, kb);
+
+ /* insertlink(lb, prevlink, newlink): newlink komt na prevlink */
+ BLI_insertlink(&key->block, kb->next, kb);
+
+ doit= 1;
+ break;
+ }
+ }
+ kb= kb->next;
+ }
+ }
+
+}
+
+/**************** do the key ****************/
+
+
+void set_four_ipo(float d, float *data, int type)
+{
+ float d2, d3, fc;
+
+ if(type==KEY_LINEAR) {
+ data[0]= 0.0f;
+ data[1]= 1.0f-d;
+ data[2]= d;
+ data[3]= 0.0f;
+ }
+ else {
+ d2= d*d;
+ d3= d2*d;
+
+ if(type==KEY_CARDINAL) {
+
+ fc= 0.71f;
+
+ data[0]= -fc*d3 +2.0f*fc*d2 -fc*d;
+ data[1]= (2.0f-fc)*d3 +(fc-3.0f)*d2 +1.0f;
+ data[2]= (fc-2.0f)*d3 +(3.0f-2.0f*fc)*d2 +fc*d;
+ data[3]= fc*d3 -fc*d2;
+ }
+ else if(type==KEY_BSPLINE) {
+
+ data[0]= -0.1666f*d3 +0.5f*d2 -0.5f*d +0.16666f;
+ data[1]= 0.5f*d3 -d2 +0.6666f;
+ data[2]= -0.5f*d3 +0.5f*d2 +0.5f*d +0.1666f;
+ data[3]= 0.1666f*d3 ;
+ }
+ }
+}
+
+void set_afgeleide_four_ipo(float d, float *data, int type)
+{
+ float d2, fc;
+
+ if(type==KEY_LINEAR) {
+
+ }
+ else {
+ d2= d*d;
+
+ if(type==KEY_CARDINAL) {
+
+ fc= 0.71f;
+
+ data[0]= -3.0f*fc*d2 +4.0f*fc*d -fc;
+ data[1]= 3.0f*(2.0f-fc)*d2 +2.0f*(fc-3.0f)*d;
+ data[2]= 3.0f*(fc-2.0f)*d2 +2.0f*(3.0f-2.0f*fc)*d +fc;
+ data[3]= 3.0f*fc*d2 -2.0f*fc*d;
+ }
+ else if(type==KEY_BSPLINE) {
+
+ data[0]= -0.1666f*3.0f*d2 +d -0.5f;
+ data[1]= 1.5f*d2 -2.0f*d;
+ data[2]= -1.5f*d2 +d +0.5f;
+ data[3]= 0.1666f*3.0f*d2 ;
+ }
+ }
+}
+
+int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl)
+{
+ /* return 1 betekent k[2] is de positie, 0 is interpoleren */
+ KeyBlock *k1, *firstkey;
+ float d, dpos, ofs=0, lastpos, temp, fval[4];
+ short bsplinetype;
+
+ firstkey= lb->first;
+ k1= lb->last;
+ lastpos= k1->pos;
+ dpos= lastpos - firstkey->pos;
+
+ if(fac < firstkey->pos) fac= firstkey->pos;
+ else if(fac > k1->pos) fac= k1->pos;
+
+ k1=k[0]=k[1]=k[2]=k[3]= firstkey;
+ t[0]=t[1]=t[2]=t[3]= k1->pos;
+
+ /* if(fac<0.0 || fac>1.0) return 1; */
+
+ if(k1->next==0) return 1;
+
+ if(cycl) { /* voorsorteren */
+ k[2]= k1->next;
+ k[3]= k[2]->next;
+ if(k[3]==0) k[3]=k1;
+ while(k1) {
+ if(k1->next==0) k[0]=k1;
+ k1=k1->next;
+ }
+ k1= k[1];
+ t[0]= k[0]->pos;
+ t[1]+= dpos;
+ t[2]= k[2]->pos + dpos;
+ t[3]= k[3]->pos + dpos;
+ fac+= dpos;
+ ofs= dpos;
+ if(k[3]==k[1]) {
+ t[3]+= dpos;
+ ofs= 2.0f*dpos;
+ }
+ if(fac<t[1]) fac+= dpos;
+ k1= k[3];
+ }
+ else { /* voorsorteren */
+ /* waarom dit voorsorteren niet eerder gedaan? voor juist interpoleren in begin noodz. */
+ k[2]= k1->next;
+ t[2]= k[2]->pos;
+ k[3]= k[2]->next;
+ if(k[3]==0) k[3]= k[2];
+ t[3]= k[3]->pos;
+ k1= k[3];
+ }
+
+ while( t[2]<fac ) { /* goede plek vinden */
+ if(k1->next==0) {
+ if(cycl) {
+ k1= firstkey;
+ ofs+= dpos;
+ }
+ else if(t[2]==t[3]) break;
+ }
+ else k1= k1->next;
+
+ t[0]= t[1];
+ k[0]= k[1];
+ t[1]= t[2];
+ k[1]= k[2];
+ t[2]= t[3];
+ k[2]= k[3];
+ t[3]= k1->pos+ofs;
+ k[3]= k1;
+
+ if(ofs>2.1+lastpos) break;
+ }
+
+ bsplinetype= 0;
+ if(k[1]->type==KEY_BSPLINE || k[2]->type==KEY_BSPLINE) bsplinetype= 1;
+
+
+ if(cycl==0) {
+ if(bsplinetype==0) { /* B spline gaat niet door de punten */
+ if(fac<=t[1]) { /* fac voor 1e key */
+ t[2]= t[1];
+ k[2]= k[1];
+ return 1;
+ }
+ if(fac>=t[2] ) { /* fac na 2e key */
+ return 1;
+ }
+ }
+ else if(fac>t[2]) { /* laatste key */
+ fac= t[2];
+ k[3]= k[2];
+ t[3]= t[2];
+ }
+ }
+
+ d= t[2]-t[1];
+ if(d==0.0) {
+ if(bsplinetype==0) {
+ return 1; /* beide keys gelijk */
+ }
+ }
+ else d= (fac-t[1])/d;
+
+ /* interpolatie */
+
+ set_four_ipo(d, t, k[1]->type);
+
+ if(k[1]->type != k[2]->type) {
+ set_four_ipo(d, fval, k[2]->type);
+
+ temp= 1.0f-d;
+ t[0]= temp*t[0]+ d*fval[0];
+ t[1]= temp*t[1]+ d*fval[1];
+ t[2]= temp*t[2]+ d*fval[2];
+ t[3]= temp*t[3]+ d*fval[3];
+ }
+
+ return 0;
+
+}
+
+void flerp(int aantal, float *in, float *f0, float *f1, float *f2, float *f3, float *t)
+{
+ int a;
+
+ for(a=0; a<aantal; a++) {
+ in[a]= t[0]*f0[a]+t[1]*f1[a]+t[2]*f2[a]+t[3]*f3[a];
+ }
+}
+
+void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *k, int mode)
+{
+ float ktot = 0.0, kd = 0.0;
+ int elemsize, poinsize = 0, a, *ofsp, ofs[32], flagflo=0;
+ char *k1;
+ char *cp, elemstr[8];
+
+ if(key->from==0) return;
+
+ if( GS(key->from->name)==ID_ME ) {
+ ofs[0]= sizeof(MVert);
+ ofs[1]= 0;
+ poinsize= ofs[0];
+ }
+ else if( GS(key->from->name)==ID_LT ) {
+ ofs[0]= sizeof(BPoint);
+ ofs[1]= 0;
+ poinsize= ofs[0];
+ }
+ else if( GS(key->from->name)==ID_CU ) {
+ if(mode==KEY_BPOINT) ofs[0]= sizeof(BPoint);
+ else ofs[0]= sizeof(BezTriple);
+
+ ofs[1]= 0;
+ poinsize= ofs[0];
+ }
+
+
+ if(end>tot) end= tot;
+
+ k1= k->data;
+
+ if(tot != k->totelem) {
+ ktot= 0.0;
+ flagflo= 1;
+ if(k->totelem) {
+ kd= k->totelem/(float)tot;
+ }
+ else return;
+ }
+
+ /* deze uitzondering is om slurphing mogelijk te maken */
+ if(start!=0) {
+
+ poin+= poinsize*start;
+
+ if(flagflo) {
+ ktot+= start*kd;
+ a= (int)floor(ktot);
+ if(a) {
+ ktot-= a;
+ k1+= a*key->elemsize;
+ }
+ }
+ else k1+= start*key->elemsize;
+ }
+
+
+ if(mode==KEY_BEZTRIPLE) {
+ elemstr[0]= 1;
+ elemstr[1]= IPO_BEZTRIPLE;
+ elemstr[2]= 0;
+ }
+
+ /* alleen in dit stuk, hierboven niet! */
+ elemsize= key->elemsize;
+ if(mode==KEY_BEZTRIPLE) elemsize*= 3;
+
+ for(a=start; a<end; a++) {
+ cp= key->elemstr;
+ if(mode==KEY_BEZTRIPLE) cp= elemstr;
+
+ ofsp= ofs;
+
+ while( cp[0] ) {
+
+ switch(cp[1]) {
+ case IPO_FLOAT:
+
+ memcpy(poin, k1, 4*cp[0]);
+ poin+= ofsp[0];
+
+ break;
+ case IPO_BPOINT:
+ memcpy(poin, k1, 3*4);
+ memcpy(poin+16, k1+12, 4);
+
+ poin+= ofsp[0];
+
+ break;
+ case IPO_BEZTRIPLE:
+ memcpy(poin, k1, 4*12);
+ poin+= ofsp[0];
+
+ break;
+ }
+
+ cp+= 2; ofsp++;
+ }
+
+ /* gaan we moeilijk doen */
+ if(flagflo) {
+ ktot+= kd;
+ while(ktot>=1.0) {
+ ktot-= 1.0;
+ k1+= elemsize;
+ }
+ }
+ else k1+= elemsize;
+
+ if(mode==KEY_BEZTRIPLE) a+=2;
+ }
+}
+
+void cp_cu_key(Curve *cu, KeyBlock *kb, int start, int end)
+{
+ Nurb *nu;
+ int a, step = 0, tot, a1, a2;
+ char *poin;
+
+ tot= count_curveverts(&cu->nurb);
+ nu= cu->nurb.first;
+ a= 0;
+ while(nu) {
+ if(nu->bp) {
+
+ step= nu->pntsu*nu->pntsv;
+
+ /* uitzondering omdat keys graag met volledige blokken werken */
+ poin= (char *)nu->bp->vec;
+ poin -= a*sizeof(BPoint);
+
+ a1= MAX2(a, start);
+ a2= MIN2(a+step, end);
+
+ if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, KEY_BPOINT);
+ }
+ else if(nu->bezt) {
+
+ step= 3*nu->pntsu;
+
+ poin= (char *)nu->bezt->vec;
+ poin -= a*sizeof(BezTriple);
+
+ a1= MAX2(a, start);
+ a2= MIN2(a+step, end);
+
+ if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, KEY_BEZTRIPLE);
+
+ }
+ a+= step;
+ nu=nu->next;
+ }
+}
+
+
+void rel_flerp(int aantal, float *in, float *ref, float *out, float fac)
+{
+ int a;
+
+ for(a=0; a<aantal; a++) {
+ in[a]-= fac*(ref[a]-out[a]);
+ }
+}
+
+
+
+void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, float ctime, int mode)
+{
+ KeyBlock *kb;
+ IpoCurve *icu;
+ float fac[32], fval;
+ int *ofsp, ofs[3], elemsize, a, b;
+ char *cp, *poin, *reffrom, *from, elemstr[8];
+
+ if(key->from==0) return;
+ if(key->ipo==0) return;
+
+ if( GS(key->from->name)==ID_ME ) {
+ ofs[0]= sizeof(MVert);
+ ofs[1]= 0;
+ }
+ else if( GS(key->from->name)==ID_LT ) {
+ ofs[0]= sizeof(BPoint);
+ ofs[1]= 0;
+ }
+ else if( GS(key->from->name)==ID_CU ) {
+ if(mode==KEY_BPOINT) ofs[0]= sizeof(BPoint);
+ else ofs[0]= sizeof(BezTriple);
+
+ ofs[1]= 0;
+ }
+
+ if(end>tot) end= tot;
+
+ /* in geval beztriple */
+ elemstr[0]= 1; /* aantal ipofloats */
+ elemstr[1]= IPO_BEZTRIPLE;
+ elemstr[2]= 0;
+
+ /* alleen in dit stuk, hierboven niet! */
+ elemsize= key->elemsize;
+ if(mode==KEY_BEZTRIPLE) elemsize*= 3;
+
+ /* step one: fetch ipo values */
+ icu= key->ipo->curve.first;
+ for(a=0; a<KEY_TOTIPO; a++) fac[a]= 0.0;
+ while(icu) {
+ fac[icu->adrcode]= icu->curval;
+ icu= icu->next;
+ }
+
+ /* step 2 init */
+ cp_key(start, end, tot, basispoin, key, key->refkey, mode);
+
+ /* step 3: do it */
+
+ a= 1;
+ kb= key->block.first;
+ while(kb) {
+
+ if(kb!=key->refkey) {
+ fval= fac[a];
+ a++;
+ if(a==32) break;
+
+ /* no difference allowed */
+ if(kb->totelem==tot) {
+
+ poin= basispoin;
+ reffrom= key->refkey->data;
+ from= kb->data;
+
+ poin+= start*ofs[0];
+ reffrom+= elemsize*start;
+ from+= elemsize*start;
+
+ for(b=start; b<end; b++) {
+
+ cp= key->elemstr;
+ if(mode==KEY_BEZTRIPLE) cp= elemstr;
+
+ ofsp= ofs;
+
+ while( cp[0] ) { /* cp[0]==aantal */
+
+ switch(cp[1]) {
+ case IPO_FLOAT:
+ rel_flerp(cp[0], (float *)poin, (float *)reffrom, (float *)from, fval);
+
+ break;
+ case IPO_BPOINT:
+ rel_flerp(3, (float *)poin, (float *)reffrom, (float *)from, fval);
+ rel_flerp(1, (float *)(poin+16), (float *)(reffrom+16), (float *)(from+16), fval);
+
+ break;
+ case IPO_BEZTRIPLE:
+ rel_flerp(9, (float *)poin, (float *)reffrom, (float *)from, fval);
+
+ break;
+ }
+
+ poin+= ofsp[0];
+
+ cp+= 2;
+ ofsp++;
+ }
+
+ reffrom+= elemsize;
+ from+= elemsize;
+
+ }
+ }
+ }
+ kb= kb->next;
+ }
+}
+
+
+void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock **k, float *t, int mode)
+{
+ float k1tot = 0.0, k2tot = 0.0, k3tot = 0.0, k4tot = 0.0;
+ float k1d = 0.0, k2d = 0.0, k3d = 0.0, k4d = 0.0;
+ int a, ofs[32], *ofsp;
+ int flagdo= 15, flagflo=0, elemsize, poinsize=0;
+ char *k1, *k2, *k3, *k4;
+ char *cp, elemstr[8];;
+
+ if(key->from==0) return;
+
+ if( GS(key->from->name)==ID_ME ) {
+ ofs[0]= sizeof(MVert);
+ ofs[1]= 0;
+ poinsize= ofs[0];
+ }
+ else if( GS(key->from->name)==ID_LT ) {
+ ofs[0]= sizeof(BPoint);
+ ofs[1]= 0;
+ poinsize= ofs[0];
+ }
+ else if( GS(key->from->name)==ID_CU ) {
+ if(mode==KEY_BPOINT) ofs[0]= sizeof(BPoint);
+ else ofs[0]= sizeof(BezTriple);
+
+ ofs[1]= 0;
+ poinsize= ofs[0];
+ }
+
+ if(end>tot) end= tot;
+
+ k1= k[0]->data;
+ k2= k[1]->data;
+ k3= k[2]->data;
+ k4= k[3]->data;
+
+ /* testen op meer of minder punten (per key!) */
+ if(tot != k[0]->totelem) {
+ k1tot= 0.0;
+ flagflo |= 1;
+ if(k[0]->totelem) {
+ k1d= k[0]->totelem/(float)tot;
+ }
+ else flagdo -= 1;
+ }
+ if(tot != k[1]->totelem) {
+ k2tot= 0.0;
+ flagflo |= 2;
+ if(k[0]->totelem) {
+ k2d= k[1]->totelem/(float)tot;
+ }
+ else flagdo -= 2;
+ }
+ if(tot != k[2]->totelem) {
+ k3tot= 0.0;
+ flagflo |= 4;
+ if(k[0]->totelem) {
+ k3d= k[2]->totelem/(float)tot;
+ }
+ else flagdo -= 4;
+ }
+ if(tot != k[3]->totelem) {
+ k4tot= 0.0;
+ flagflo |= 8;
+ if(k[0]->totelem) {
+ k4d= k[3]->totelem/(float)tot;
+ }
+ else flagdo -= 8;
+ }
+
+ /* deze uitzondering is om slurphing mogelijk te maken */
+ if(start!=0) {
+
+ poin+= poinsize*start;
+
+ if(flagdo & 1) {
+ if(flagflo & 1) {
+ k1tot+= start*k1d;
+ a= (int)floor(k1tot);
+ if(a) {
+ k1tot-= a;
+ k1+= a*key->elemsize;
+ }
+ }
+ else k1+= start*key->elemsize;
+ }
+ if(flagdo & 2) {
+ if(flagflo & 2) {
+ k2tot+= start*k2d;
+ a= (int)floor(k2tot);
+ if(a) {
+ k2tot-= a;
+ k2+= a*key->elemsize;
+ }
+ }
+ else k2+= start*key->elemsize;
+ }
+ if(flagdo & 4) {
+ if(flagflo & 4) {
+ k3tot+= start*k3d;
+ a= (int)floor(k3tot);
+ if(a) {
+ k3tot-= a;
+ k3+= a*key->elemsize;
+ }
+ }
+ else k3+= start*key->elemsize;
+ }
+ if(flagdo & 8) {
+ if(flagflo & 8) {
+ k4tot+= start*k4d;
+ a= (int)floor(k4tot);
+ if(a) {
+ k4tot-= a;
+ k4+= a*key->elemsize;
+ }
+ }
+ else k4+= start*key->elemsize;
+ }
+
+ }
+
+ /* in geval beztriple */
+ elemstr[0]= 1; /* aantal ipofloats */
+ elemstr[1]= IPO_BEZTRIPLE;
+ elemstr[2]= 0;
+
+ /* alleen in dit stuk, hierboven niet! */
+ elemsize= key->elemsize;
+ if(mode==KEY_BEZTRIPLE) elemsize*= 3;
+
+ for(a=start; a<end; a++) {
+
+ cp= key->elemstr;
+ if(mode==KEY_BEZTRIPLE) cp= elemstr;
+
+ ofsp= ofs;
+
+ while( cp[0] ) { /* cp[0]==aantal */
+
+ switch(cp[1]) {
+ case IPO_FLOAT:
+ flerp(cp[0], (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
+ poin+= ofsp[0];
+
+ break;
+ case IPO_BPOINT:
+ flerp(3, (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
+ flerp(1, (float *)(poin+16), (float *)(k1+12), (float *)(k2+12), (float *)(k3+12), (float *)(k4+12), t);
+
+ poin+= ofsp[0];
+
+ break;
+ case IPO_BEZTRIPLE:
+ flerp(9, (void *)poin, (void *)k1, (void *)k2, (void *)k3, (void *)k4, t);
+ poin+= ofsp[0];
+
+ break;
+ }
+
+
+ cp+= 2;
+ ofsp++;
+ }
+ /* gaan we moeilijk doen: als keys van lengte verschillen */
+ if(flagdo & 1) {
+ if(flagflo & 1) {
+ k1tot+= k1d;
+ while(k1tot>=1.0) {
+ k1tot-= 1.0;
+ k1+= elemsize;
+ }
+ }
+ else k1+= elemsize;
+ }
+ if(flagdo & 2) {
+ if(flagflo & 2) {
+ k2tot+= k2d;
+ while(k2tot>=1.0) {
+ k2tot-= 1.0;
+ k2+= elemsize;
+ }
+ }
+ else k2+= elemsize;
+ }
+ if(flagdo & 4) {
+ if(flagflo & 4) {
+ k3tot+= k3d;
+ while(k3tot>=1.0) {
+ k3tot-= 1.0;
+ k3+= elemsize;
+ }
+ }
+ else k3+= elemsize;
+ }
+ if(flagdo & 8) {
+ if(flagflo & 8) {
+ k4tot+= k4d;
+ while(k4tot>=1.0) {
+ k4tot-= 1.0;
+ k4+= elemsize;
+ }
+ }
+ else k4+= elemsize;
+ }
+
+ if(mode==KEY_BEZTRIPLE) a+= 2;
+ }
+}
+
+
+
+void do_mesh_key(Mesh *me)
+{
+ KeyBlock *k[4];
+ float cfra, ctime, t[4], delta, loc[3], size[3];
+ int a, flag = 0, step;
+
+ if(me->totvert==0) return;
+ if(me->key==0) return;
+ if(me->key->block.first==0) return;
+
+ if(me->key->slurph && me->key->type!=KEY_RELATIVE ) {
+ delta= me->key->slurph;
+ delta/= me->totvert;
+
+ step= 1;
+ if(me->totvert>100 && slurph_opt) {
+ step= me->totvert/50;
+ delta*= step;
+ /* in do_key en cp_key wordt a>tot afgevangen */
+ }
+
+ cfra= G.scene->r.cfra;
+
+ for(a=0; a<me->totvert; a+=step, cfra+= delta) {
+
+ ctime= bsystem_time(0, 0, cfra, 0.0);
+ if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) {
+ ctime /= 100.0;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+
+ flag= setkeys(ctime, &me->key->block, k, t, 0);
+ if(flag==0) {
+
+ do_key(a, a+step, me->totvert, (char *)me->mvert->co, me->key, k, t, 0);
+ }
+ else {
+ cp_key(a, a+step, me->totvert, (char *)me->mvert->co, me->key, k[2], 0);
+ }
+ }
+
+ if(flag && k[2]==me->key->refkey) tex_space_mesh(me);
+ else boundbox_mesh(me, loc, size);
+
+ }
+ else {
+
+ ctime= bsystem_time(0, 0, (float)G.scene->r.cfra, 0.0);
+ if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) {
+ ctime /= 100.0;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+
+ if(me->key->type==KEY_RELATIVE) {
+ do_rel_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, ctime, 0);
+ }
+ else {
+ flag= setkeys(ctime, &me->key->block, k, t, 0);
+ if(flag==0) {
+
+ do_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k, t, 0);
+ }
+ else {
+ cp_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k[2], 0);
+
+ }
+
+ if(flag && k[2]==me->key->refkey) tex_space_mesh(me);
+ else boundbox_mesh(me, loc, size);
+ }
+ }
+}
+
+void do_cu_key(Curve *cu, KeyBlock **k, float *t)
+{
+ Nurb *nu;
+ int a, step = 0, tot;
+ char *poin;
+
+ tot= count_curveverts(&cu->nurb);
+ nu= cu->nurb.first;
+ a= 0;
+ while(nu) {
+ if(nu->bp) {
+
+ step= nu->pntsu*nu->pntsv;
+
+ /* uitzondering omdat keys graag met volledige blokken werken */
+ poin= (char *)nu->bp->vec;
+ poin -= a*sizeof(BPoint);
+
+ do_key(a, a+step, tot, poin, cu->key, k, t, KEY_BPOINT);
+ }
+ else if(nu->bezt) {
+
+ step= 3*nu->pntsu;
+
+ poin= (char *)nu->bezt->vec;
+ poin -= a*sizeof(BezTriple);
+
+ do_key(a, a+step, tot, poin, cu->key, k, t, KEY_BEZTRIPLE);
+
+ }
+ a+= step;
+ nu=nu->next;
+ }
+}
+
+void do_rel_cu_key(Curve *cu, float ctime)
+{
+ Nurb *nu;
+ int a, step = 0, tot;
+ char *poin;
+
+ tot= count_curveverts(&cu->nurb);
+ nu= cu->nurb.first;
+ a= 0;
+ while(nu) {
+ if(nu->bp) {
+
+ step= nu->pntsu*nu->pntsv;
+
+ /* uitzondering omdat keys graag met volledige blokken werken */
+ poin= (char *)nu->bp->vec;
+ poin -= a*sizeof(BPoint);
+
+ do_rel_key(a, a+step, tot, poin, cu->key, ctime, KEY_BPOINT);
+ }
+ else if(nu->bezt) {
+
+ step= 3*nu->pntsu;
+
+ poin= (char *)nu->bezt->vec;
+ poin -= a*sizeof(BezTriple);
+
+ do_rel_key(a, a+step, tot, poin, cu->key, ctime, KEY_BEZTRIPLE);
+
+ }
+ a+= step;
+ nu=nu->next;
+ }
+}
+
+void do_curve_key(Curve *cu)
+{
+ KeyBlock *k[4];
+ float cfra, ctime, t[4], delta;
+ int a, flag = 0, step = 0, tot;
+
+ tot= count_curveverts(&cu->nurb);
+
+ if(tot==0) return;
+ if(cu->key==0) return;
+ if(cu->key->block.first==0) return;
+
+ if(cu->key->slurph) {
+ delta= cu->key->slurph;
+ delta/= tot;
+
+ step= 1;
+ if(tot>100 && slurph_opt) {
+ step= tot/50;
+ delta*= step;
+ /* in do_key en cp_key wordt a>tot afgevangen */
+ }
+
+ cfra= G.scene->r.cfra;
+
+ for(a=0; a<tot; a+=step, cfra+= delta) {
+
+ ctime= bsystem_time(0, 0, cfra, 0.0);
+ if(calc_ipo_spec(cu->key->ipo, KEY_SPEED, &ctime)==0) {
+ ctime /= 100.0;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+
+ flag= setkeys(ctime, &cu->key->block, k, t, 0);
+ if(flag==0) {
+
+ /* do_key(a, a+step, tot, (char *)cu->mvert->co, cu->key, k, t, 0); */
+ }
+ else {
+ /* cp_key(a, a+step, tot, (char *)cu->mvert->co, cu->key, k[2],0); */
+ }
+ }
+
+ if(flag && k[2]==cu->key->refkey) tex_space_curve(cu);
+
+
+ }
+ else {
+
+ ctime= bsystem_time(0, 0, (float)G.scene->r.cfra, 0.0);
+ if(calc_ipo_spec(cu->key->ipo, KEY_SPEED, &ctime)==0) {
+ ctime /= 100.0;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+
+ if(cu->key->type==KEY_RELATIVE) {
+ do_rel_cu_key(cu, ctime);
+ }
+ else {
+ flag= setkeys(ctime, &cu->key->block, k, t, 0);
+
+ if(flag==0) do_cu_key(cu, k, t);
+ else cp_cu_key(cu, k[2], 0, tot);
+
+ if(flag && k[2]==cu->key->refkey) tex_space_curve(cu);
+ }
+ }
+}
+
+void do_latt_key(Lattice *lt)
+{
+ KeyBlock *k[4];
+ float delta, cfra, ctime, t[4];
+ int a, tot, flag;
+
+ if(lt->key==0) return;
+ if(lt->key->block.first==0) return;
+
+ tot= lt->pntsu*lt->pntsv*lt->pntsw;
+
+ if(lt->key->slurph) {
+ delta= lt->key->slurph;
+ delta/= (float)tot;
+
+ cfra= G.scene->r.cfra;
+
+ for(a=0; a<tot; a++, cfra+= delta) {
+
+ ctime= bsystem_time(0, 0, cfra, 0.0);
+ if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &ctime)==0) {
+ ctime /= 100.0;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+
+ flag= setkeys(ctime, &lt->key->block, k, t, 0);
+ if(flag==0) {
+
+ do_key(a, a+1, tot, (char *)lt->def->vec, lt->key, k, t, 0);
+ }
+ else {
+ cp_key(a, a+1, tot, (char *)lt->def->vec, lt->key, k[2], 0);
+ }
+ }
+ }
+ else {
+ ctime= bsystem_time(0, 0, (float)G.scene->r.cfra, 0.0);
+ if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &ctime)==0) {
+ ctime /= 100.0;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+
+ if(lt->key->type==KEY_RELATIVE) {
+ do_rel_key(0, tot, tot, (char *)lt->def->vec, lt->key, ctime, 0);
+ }
+ else {
+
+ flag= setkeys(ctime, &lt->key->block, k, t, 0);
+ if(flag==0) {
+ do_key(0, tot, tot, (char *)lt->def->vec, lt->key, k, t, 0);
+ }
+ else {
+ cp_key(0, tot, tot, (char *)lt->def->vec, lt->key, k[2], 0);
+ }
+ }
+ }
+
+ if(lt->flag & LT_OUTSIDE) outside_lattice(lt);
+}
+
+
+
+void do_all_keys()
+{
+ Key *key;
+ int idcode;
+
+ key= G.main->key.first;
+ while(key) {
+ if(key->from) {
+ idcode= GS(key->from->name);
+
+ if(idcode==ID_ME) do_mesh_key( (Mesh *)key->from);
+ else if(idcode==ID_CU) do_curve_key( (Curve *)key->from);
+ else if(idcode==ID_LT) do_latt_key( (Lattice *)key->from);
+ }
+ key= key->id.next;
+ }
+}
+
+void do_ob_key(Object *ob)
+{
+ if(ob->type==OB_MESH) do_mesh_key( ob->data);
+ else if(ob->type==OB_CURVE) do_curve_key( ob->data);
+ else if(ob->type==OB_SURF) do_curve_key( ob->data);
+ else if(ob->type==OB_LATTICE) do_latt_key( ob->data);
+}
+
+void do_spec_key(Key *key)
+{
+ int idcode;
+
+ if(key==0) return;
+
+ idcode= GS(key->from->name);
+
+ if(idcode==ID_ME) do_mesh_key( (Mesh *)key->from);
+ else if(idcode==ID_CU) do_curve_key( (Curve *)key->from);
+ else if(idcode==ID_LT) do_latt_key( (Lattice *)key->from);
+
+}
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
new file mode 100644
index 00000000000..a6895d2a8ea
--- /dev/null
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -0,0 +1,633 @@
+/**
+ * lattice.c MIXED MODEL
+ * june 2001 ton
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_ika_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_armature.h"
+#include "BKE_library.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_screen.h"
+#include "BKE_displist.h"
+#include "BKE_lattice.h"
+#include "BKE_key.h"
+#include "BKE_object.h"
+#include "BKE_ika.h"
+
+Lattice *editLatt=0, *deformLatt=0;
+
+float *latticedata=0, latmat[4][4];
+int lt_applyflag= 0;
+
+void resizelattice(Lattice *lt)
+{
+ BPoint *bp;
+ int u, v, w;
+ float vec[3], fu, fv, fw, du=0.0, dv=0.0, dw=0.0;
+
+
+ MEM_freeN(lt->def);
+ lt->def= MEM_callocN(lt->pntsu*lt->pntsv*lt->pntsw*sizeof(BPoint), "lattice bp");
+
+ bp= lt->def;
+
+ while(lt->pntsu*lt->pntsv*lt->pntsw > 32000) {
+ if( lt->pntsu>=lt->pntsv && lt->pntsu>=lt->pntsw) lt->pntsu--;
+ else if( lt->pntsv>=lt->pntsu && lt->pntsv>=lt->pntsw) lt->pntsv--;
+ else lt->pntsw--;
+ }
+
+ calc_lat_fudu(lt->flag, lt->pntsu, &fu, &du);
+ calc_lat_fudu(lt->flag, lt->pntsv, &fv, &dv);
+ calc_lat_fudu(lt->flag, lt->pntsw, &fw, &dw);
+
+ vec[2]= fw;
+ for(w=0; w<lt->pntsw; w++) {
+ vec[1]= fv;
+ for(v=0; v<lt->pntsv; v++) {
+ vec[0]= fu;
+ for(u=0; u<lt->pntsu; u++, bp++) {
+ VECCOPY(bp->vec, vec);
+ vec[0]+= du;
+ }
+ vec[1]+= dv;
+ }
+ vec[2]+= dw;
+ }
+}
+
+Lattice *add_lattice()
+{
+ Lattice *lt;
+
+ lt= alloc_libblock(&G.main->latt, ID_LT, "Lattice");
+
+ lt->pntsu=lt->pntsv=lt->pntsw= 2;
+ lt->flag= LT_GRID;
+
+ lt->typeu= lt->typev= lt->typew= KEY_BSPLINE;
+
+ /* tijdelijk */
+ lt->def= MEM_callocN(sizeof(BPoint), "lattvert");
+
+ resizelattice(lt); /* maakt een regelmatige lattice */
+
+ return lt;
+}
+
+Lattice *copy_lattice(Lattice *lt)
+{
+ Lattice *ltn;
+
+ ltn= copy_libblock(lt);
+ ltn->def= MEM_dupallocN(lt->def);
+
+ id_us_plus((ID *)ltn->ipo);
+
+ ltn->key= copy_key(ltn->key);
+ if(ltn->key) ltn->key->from= (ID *)ltn;
+
+ return ltn;
+}
+
+void free_lattice(Lattice *lt)
+{
+ if(lt->def) MEM_freeN(lt->def);
+}
+
+
+void make_local_lattice(Lattice *lt)
+{
+ Object *ob;
+ Lattice *ltn;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(lt->id.lib==0) return;
+ if(lt->id.us==1) {
+ lt->id.lib= 0;
+ lt->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)lt, 0);
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==lt) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ lt->id.lib= 0;
+ lt->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)lt, 0);
+ }
+ else if(local && lib) {
+ ltn= copy_lattice(lt);
+ ltn->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==lt) {
+
+ if(ob->id.lib==0) {
+ ob->data= ltn;
+ ltn->id.us++;
+ lt->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+
+
+void calc_lat_fudu(int flag, int res, float *fu, float *du)
+{
+
+ if(res==1) {
+ *fu= 0.0;
+ *du= 0.0;
+ }
+ else if(flag & LT_GRID) {
+ *fu= -0.5f*(res-1);
+ *du= 1.0f;
+ }
+ else {
+ *fu= -1.0f;
+ *du= 2.0f/(res-1);
+ }
+
+}
+
+void init_latt_deform(Object *oblatt, Object *ob)
+{
+ /* we maken een array met alle verschillen */
+ BPoint *bp;
+ float *fp, imat[4][4];
+ float vec[3], fu, fv, fw, du=0.0, dv=0.0, dw=0.0;
+ int u, v, w;
+
+ if(oblatt==G.obedit) deformLatt= editLatt;
+ else deformLatt= oblatt->data;
+
+ fp= latticedata= MEM_mallocN(sizeof(float)*3*deformLatt->pntsu*deformLatt->pntsv*deformLatt->pntsw, "latticedata");
+
+ bp= deformLatt->def;
+
+ if(ob) where_is_object(ob);
+
+ /* bijv bij particle systeem: ob==0 */
+ if(ob==0) {
+ /* in deformspace, matrix berekenen */
+ Mat4Invert(latmat, oblatt->obmat);
+
+ /* terug: in deform array verwerken */
+ Mat4Invert(imat, latmat);
+ }
+ else {
+ /* in deformspace, matrix berekenen */
+ Mat4Invert(imat, oblatt->obmat);
+ Mat4MulMat4(latmat, ob->obmat, imat);
+
+ /* terug: in deform array verwerken */
+ Mat4Invert(imat, latmat);
+ }
+ calc_lat_fudu(deformLatt->flag, deformLatt->pntsu, &fu, &du);
+ calc_lat_fudu(deformLatt->flag, deformLatt->pntsv, &fv, &dv);
+ calc_lat_fudu(deformLatt->flag, deformLatt->pntsw, &fw, &dw);
+
+ /* we berekenen hier steeds de u v w lattice coordinaten, weinig reden ze te onthouden */
+
+ vec[2]= fw;
+ for(w=0; w<deformLatt->pntsw; w++) {
+ vec[1]= fv;
+ for(v=0; v<deformLatt->pntsv; v++) {
+ vec[0]= fu;
+ for(u=0; u<deformLatt->pntsu; u++, bp++) {
+
+ VecSubf(fp, bp->vec, vec);
+ Mat4Mul3Vecfl(imat, fp);
+
+ vec[0]+= du;
+ fp+= 3;
+ }
+ vec[1]+= dv;
+ }
+ vec[2]+= dw;
+ }
+}
+
+void calc_latt_deform(float *co)
+{
+ Lattice *lt;
+ float fu, du, u, v, w, tu[4], tv[4], tw[4];
+ float *fpw, *fpv, *fpu, vec[3];
+ int ui, vi, wi, uu, vv, ww;
+
+ if(latticedata==0) return;
+
+ lt= deformLatt; /* kortere notatie! */
+
+ /* co is in lokale coords, met latmat behandelen */
+
+ VECCOPY(vec, co);
+ Mat4MulVecfl(latmat, vec);
+
+ /* u v w coords */
+
+ if(lt->pntsu>1) {
+ calc_lat_fudu(lt->flag, lt->pntsu, &fu, &du);
+ u= (vec[0]-fu)/du;
+ ui= (int)floor(u);
+ u -= ui;
+ set_four_ipo(u, tu, lt->typeu);
+ }
+ else {
+ tu[0]= tu[2]= tu[3]= 0.0; tu[1]= 1.0;
+ ui= 0;
+ }
+
+ if(lt->pntsv>1) {
+ calc_lat_fudu(lt->flag, lt->pntsv, &fu, &du);
+ v= (vec[1]-fu)/du;
+ vi= (int)floor(v);
+ v -= vi;
+ set_four_ipo(v, tv, lt->typev);
+ }
+ else {
+ tv[0]= tv[2]= tv[3]= 0.0; tv[1]= 1.0;
+ vi= 0;
+ }
+
+ if(lt->pntsw>1) {
+ calc_lat_fudu(lt->flag, lt->pntsw, &fu, &du);
+ w= (vec[2]-fu)/du;
+ wi= (int)floor(w);
+ w -= wi;
+ set_four_ipo(w, tw, lt->typew);
+ }
+ else {
+ tw[0]= tw[2]= tw[3]= 0.0; tw[1]= 1.0;
+ wi= 0;
+ }
+
+ for(ww= wi-1; ww<=wi+2; ww++) {
+ w= tw[ww-wi+1];
+
+ if(w!=0.0) {
+ if(ww>0) {
+ if(ww<lt->pntsw) fpw= latticedata + 3*ww*lt->pntsu*lt->pntsv;
+ else fpw= latticedata + 3*(lt->pntsw-1)*lt->pntsu*lt->pntsv;
+ }
+ else fpw= latticedata;
+
+ for(vv= vi-1; vv<=vi+2; vv++) {
+ v= w*tv[vv-vi+1];
+
+ if(v!=0.0) {
+ if(vv>0) {
+ if(vv<lt->pntsv) fpv= fpw + 3*vv*lt->pntsu;
+ else fpv= fpw + 3*(lt->pntsv-1)*lt->pntsu;
+ }
+ else fpv= fpw;
+
+ for(uu= ui-1; uu<=ui+2; uu++) {
+ u= v*tu[uu-ui+1];
+
+ if(u!=0.0) {
+ if(uu>0) {
+ if(uu<lt->pntsu) fpu= fpv + 3*uu;
+ else fpu= fpv + 3*(lt->pntsu-1);
+ }
+ else fpu= fpv;
+
+ co[0]+= u*fpu[0];
+ co[1]+= u*fpu[1];
+ co[2]+= u*fpu[2];
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void end_latt_deform()
+{
+
+ MEM_freeN(latticedata);
+ latticedata= 0;
+}
+
+
+int object_deform(Object *ob)
+{
+ Mesh *me;
+ Curve *cu;
+ DispList *dl;
+ MVert *mvert;
+ float *fp;
+ int a, tot;
+
+ if(ob->parent==0) return 0;
+
+ /* altijd proberen in deze fie de hele deform te doen: apply! */
+
+ if(ob->parent->type==OB_LATTICE) {
+
+ init_latt_deform(ob->parent, ob);
+
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+
+ dl= find_displist_create(&ob->disp, DL_VERTS);
+
+ mvert= me->mvert;
+ if(dl->verts) MEM_freeN(dl->verts);
+ dl->nr= me->totvert;
+ dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1");
+
+ for(a=0; a<me->totvert; a++, mvert++, fp+=3) {
+ if(lt_applyflag) calc_latt_deform(mvert->co);
+ else {
+ VECCOPY(fp, mvert->co);
+ calc_latt_deform(fp);
+ }
+ }
+ }
+ else if ELEM(ob->type, OB_CURVE, OB_SURF) {
+
+ cu= ob->data;
+ if(lt_applyflag) {
+ Nurb *nu;
+ BPoint *bp;
+
+ nu= cu->nurb.first;
+ while(nu) {
+ if(nu->bp) {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ calc_latt_deform(bp->vec);
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ }
+
+ /* when apply, do this too, looks more interactive */
+ dl= cu->disp.first;
+ while(dl) {
+
+ fp= dl->verts;
+
+ if(dl->type==DL_INDEX3) tot=dl->parts;
+ else tot= dl->nr*dl->parts;
+
+ for(a=0; a<tot; a++, fp+=3) {
+ calc_latt_deform(fp);
+ }
+
+ dl= dl->next;
+ }
+ }
+ end_latt_deform();
+
+ boundbox_displist(ob);
+
+ return 1;
+ }
+ else if(ob->parent->type==OB_ARMATURE) {
+ if (ob->partype != PARSKEL){
+ return 0;
+ }
+
+ init_armature_deform (ob->parent, ob);
+
+ switch (ob->type){
+ case OB_MESH:
+ me= ob->data;
+
+ dl= find_displist_create(&ob->disp, DL_VERTS);
+
+ mvert= me->mvert;
+ if(dl->verts) MEM_freeN(dl->verts);
+ dl->nr= me->totvert;
+ dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1");
+
+ for(a=0; a<me->totvert; a++, mvert++, fp+=3) {
+ if(lt_applyflag){
+ calc_armature_deform(ob->parent, mvert->co, a);
+ }
+ else {
+ VECCOPY(fp, mvert->co);
+ calc_armature_deform(ob->parent, fp, a);
+ }
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ boundbox_displist(ob);
+ return 1;
+ }
+ else if(ob->parent->type==OB_IKA) {
+
+ Ika *ika;
+
+ if(ob->partype!=PARSKEL) return 0;
+
+ ika= ob->parent->data;
+ if(ika->def==0) return 0;
+
+ init_skel_deform(ob->parent, ob);
+
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+
+ dl= find_displist_create(&ob->disp, DL_VERTS);
+
+ mvert= me->mvert;
+ if(dl->verts) MEM_freeN(dl->verts);
+ dl->nr= me->totvert;
+ dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1");
+
+ for(a=0; a<me->totvert; a++, mvert++, fp+=3) {
+ if(lt_applyflag) calc_skel_deform(ika, mvert->co);
+ else {
+ VECCOPY(fp, mvert->co);
+ calc_skel_deform(ika, fp);
+ }
+ }
+ }
+ else if ELEM(ob->type, OB_CURVE, OB_SURF) {
+
+ cu= ob->data;
+ if(lt_applyflag) {
+ Nurb *nu;
+ BPoint *bp;
+
+ nu= cu->nurb.first;
+ while(nu) {
+ if(nu->bp) {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ calc_skel_deform(ika, bp->vec);
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ }
+
+ /* when apply, do this too, looks more interactive */
+ dl= cu->disp.first;
+ while(dl) {
+
+ fp= dl->verts;
+ tot= dl->nr*dl->parts;
+ for(a=0; a<tot; a++, fp+=3) {
+ calc_skel_deform(ika, fp);
+ }
+
+ dl= dl->next;
+ }
+ }
+
+ boundbox_displist(ob);
+
+ return 1;
+ }
+
+ return 0;
+
+}
+
+BPoint *latt_bp(Lattice *lt, int u, int v, int w)
+{
+ return lt->def+ u + v*lt->pntsu + w*lt->pntsu*lt->pntsv;
+}
+
+void outside_lattice(Lattice *lt)
+{
+ BPoint *bp, *bp1, *bp2;
+ int u, v, w;
+ float fac1, du=0.0, dv=0.0, dw=0.0;
+
+ bp= lt->def;
+
+ if(lt->pntsu>1) du= 1.0f/((float)lt->pntsu-1);
+ if(lt->pntsv>1) dv= 1.0f/((float)lt->pntsv-1);
+ if(lt->pntsw>1) dw= 1.0f/((float)lt->pntsw-1);
+
+ for(w=0; w<lt->pntsw; w++) {
+
+ for(v=0; v<lt->pntsv; v++) {
+
+ for(u=0; u<lt->pntsu; u++, bp++) {
+ if(u==0 || v==0 || w==0 || u==lt->pntsu-1 || v==lt->pntsv-1 || w==lt->pntsw-1);
+ else {
+
+ bp->hide= 1;
+ bp->f1 &= ~SELECT;
+
+ /* u extrema */
+ bp1= latt_bp(lt, 0, v, w);
+ bp2= latt_bp(lt, lt->pntsu-1, v, w);
+
+ fac1= du*u;
+ bp->vec[0]= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
+ bp->vec[1]= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
+ bp->vec[2]= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
+
+ /* v extrema */
+ bp1= latt_bp(lt, u, 0, w);
+ bp2= latt_bp(lt, u, lt->pntsv-1, w);
+
+ fac1= dv*v;
+ bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
+ bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
+ bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
+
+ /* w extrema */
+ bp1= latt_bp(lt, u, v, 0);
+ bp2= latt_bp(lt, u, v, lt->pntsw-1);
+
+ fac1= dw*w;
+ bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
+ bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
+ bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
+
+ VecMulf(bp->vec, 0.3333333f);
+
+ }
+ }
+
+ }
+
+ }
+
+}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
new file mode 100644
index 00000000000..97ede69280c
--- /dev/null
+++ b/source/blender/blenkernel/intern/library.c
@@ -0,0 +1,905 @@
+
+/* library.c aug 94 MIXED MODEL
+ *
+ * jan 95
+ *
+ * afhandeling ID's en libraries
+ * allocceren en vrijgeven alle library data
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+/* all types are needed here, in order to do memory operations */
+#include "DNA_ID.h"
+#include "DNA_listBase.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_image_types.h"
+#include "DNA_wave_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+#include "DNA_world_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_text_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_group_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_action_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_global.h"
+#include "BKE_sound.h"
+#include "BKE_object.h"
+#include "BKE_screen.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_curve.h"
+#include "BKE_mball.h"
+ #include "BKE_text.h"
+#include "BKE_texture.h"
+#include "BKE_scene.h"
+#include "BKE_image.h"
+#include "BKE_ika.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_world.h"
+#include "BKE_font.h"
+#include "BKE_group.h"
+#include "BKE_lattice.h"
+#include "BKE_armature.h"
+#include "BKE_action.h"
+
+#define MAX_IDPUP 30 /* was 24 */
+#define MAX_LIBARRAY 100 /* was 30 */
+
+/* ************* ALGEMEEN ************************ */
+
+void id_lib_extern(ID *id)
+{
+ if(id) {
+ if(id->flag & LIB_INDIRECT) {
+ id->flag -= LIB_INDIRECT;
+ id->flag |= LIB_EXTERN;
+ }
+ }
+}
+
+void id_us_plus(ID *id)
+{
+ if(id) {
+ id->us++;
+ if(id->flag & LIB_INDIRECT) {
+ id->flag -= LIB_INDIRECT;
+ id->flag |= LIB_EXTERN;
+ }
+ }
+}
+
+ListBase *wich_libbase(Main *mainlib, short type)
+{
+ switch( type ) {
+ case ID_SCE:
+ return &(mainlib->scene);
+ case ID_LI:
+ return &(mainlib->library);
+ case ID_OB:
+ return &(mainlib->object);
+ case ID_ME:
+ return &(mainlib->mesh);
+ case ID_CU:
+ return &(mainlib->curve);
+ case ID_MB:
+ return &(mainlib->mball);
+ case ID_MA:
+ return &(mainlib->mat);
+ case ID_TE:
+ return &(mainlib->tex);
+ case ID_IM:
+ return &(mainlib->image);
+ case ID_IK:
+ return &(mainlib->ika);
+ case ID_WV:
+ return &(mainlib->wave);
+ case ID_LT:
+ return &(mainlib->latt);
+ case ID_LA:
+ return &(mainlib->lamp);
+ case ID_CA:
+ return &(mainlib->camera);
+ case ID_IP:
+ return &(mainlib->ipo);
+ case ID_KE:
+ return &(mainlib->key);
+ case ID_WO:
+ return &(mainlib->world);
+ case ID_SCR:
+ return &(mainlib->screen);
+ case ID_VF:
+ return &(mainlib->vfont);
+ case ID_TXT:
+ return &(mainlib->text);
+ case ID_SO:
+ return &(mainlib->sound);
+ case ID_SAMPLE:
+ /* declared as an external in sound.h !!! */
+ return (samples);
+ case ID_GR:
+ return &(mainlib->group);
+ case ID_AR:
+ return &(mainlib->armature);
+ case ID_AC:
+ return &(mainlib->action);
+ }
+ return 0;
+}
+
+int set_listbasepointers(Main *main, ListBase **lb)
+{
+ /* BACKWARDS! let op volgorde van vrijgeven! (mesh<->mat) */
+
+ lb[0]= &(main->ipo);
+ lb[1]= &(main->key);
+ lb[2]= &(main->image);
+ lb[3]= &(main->tex);
+ lb[4]= &(main->mat);
+ lb[5]= &(main->vfont);
+
+ /* Important!: When adding a new object type,
+ * the specific data should be inserted here
+ */
+
+ lb[6]= &(main->armature);
+ lb[7]= &(main->action);
+
+ lb[8]= &(main->mesh);
+ lb[9]= &(main->curve);
+ lb[10]= &(main->mball);
+ lb[11]= &(main->ika);
+ lb[12]= &(main->wave);
+ lb[13]= &(main->latt);
+ lb[14]= &(main->lamp);
+ lb[15]= &(main->camera);
+
+ lb[16]= &(main->world);
+ lb[17]= &(main->screen);
+ lb[18]= &(main->object);
+ lb[19]= &(main->scene);
+ lb[20]= &(main->library);
+ lb[21]= &(main->text);
+ lb[22]= &(main->sound);
+ lb[23]= &(main->group);
+
+ lb[24]= samples;
+ lb[25]= 0;
+
+ return 25;
+}
+
+/* *********** ALLOC EN FREE *****************
+
+free_libblock(ListBase *lb, ID *id )
+ lijstbasis en datablok geven, alleen ID wordt uitgelezen
+
+void *alloc_libblock(ListBase *lb, type, name)
+ hangt in lijst en geeft nieuw ID
+
+ ***************************** */
+
+static ID *alloc_libblock_notest(short type)
+{
+ ID *id= 0;
+
+ switch( type ) {
+ case ID_SCE:
+ id= MEM_callocN(sizeof(Scene), "scene");
+ break;
+ case ID_LI:
+ id= MEM_callocN(sizeof(Library), "library");
+ break;
+ case ID_OB:
+ id= MEM_callocN(sizeof(Object), "object");
+ break;
+ case ID_ME:
+ id= MEM_callocN(sizeof(Mesh), "mesh");
+ break;
+ case ID_CU:
+ id= MEM_callocN(sizeof(Curve), "curve");
+ break;
+ case ID_MB:
+ id= MEM_callocN(sizeof(MetaBall), "mball");
+ break;
+ case ID_MA:
+ id= MEM_callocN(sizeof(Material), "mat");
+ break;
+ case ID_TE:
+ id= MEM_callocN(sizeof(Tex), "tex");
+ break;
+ case ID_IM:
+ id= MEM_callocN(sizeof(Image), "image");
+ break;
+ case ID_IK:
+ id= MEM_callocN(sizeof(Ika), "ika");
+ break;
+ case ID_WV:
+ id= MEM_callocN(sizeof(Wave), "wave");
+ break;
+ case ID_LT:
+ id= MEM_callocN(sizeof(Lattice), "latt");
+ break;
+ case ID_LA:
+ id= MEM_callocN(sizeof(Lamp), "lamp");
+ break;
+ case ID_CA:
+ id= MEM_callocN(sizeof(Camera), "camera");
+ break;
+ case ID_IP:
+ id= MEM_callocN(sizeof(Ipo), "ipo");
+ break;
+ case ID_KE:
+ id= MEM_callocN(sizeof(Key), "key");
+ break;
+ case ID_WO:
+ id= MEM_callocN(sizeof(World), "world");
+ break;
+ case ID_SCR:
+ id= MEM_callocN(sizeof(bScreen), "screen");
+ break;
+ case ID_VF:
+ id= MEM_callocN(sizeof(VFont), "vfont");
+ break;
+ case ID_TXT:
+ id= MEM_callocN(sizeof(Text), "text");
+ break;
+ case ID_SO:
+ id= MEM_callocN(sizeof(bSound), "sound");
+ break;
+ case ID_SAMPLE:
+ id = MEM_callocN(sizeof(bSample), "sound");
+ break;
+ case ID_GR:
+ id= MEM_callocN(sizeof(Group), "sound");
+ break;
+ case ID_AR:
+ id = MEM_callocN(sizeof(bArmature), "armature");
+ break;
+ case ID_AC:
+ id = MEM_callocN(sizeof(bAction), "action");
+ break;
+ }
+ return id;
+}
+
+// used everywhere in blenkernel and text.c
+void *alloc_libblock(ListBase *lb, short type, char *name)
+{
+ ID *id= 0;
+
+ id= alloc_libblock_notest(type);
+ if(id) {
+ BLI_addtail(lb, id);
+ id->us= 1;
+ *( (short *)id->name )= type;
+ new_id(lb, id, name);
+ /* alfabetisch opnieuw invoegen: zit in new_id */
+ }
+ return id;
+}
+
+/* GS reads the memory pointed at in a specific ordering. There are,
+ * however two definitions for it. I have jotted them down here, both,
+ * but I think the first one is actually used. The thing is that
+ * big-endian systems might read this the wrong way round. OTOH, we
+ * constructed the IDs that are read out with this macro explicitly as
+ * well. I expect we'll sort it out soon... */
+
+/* from blendef: */
+#define GS(a) (*((short *)(a)))
+
+/* from misc_util: flip the bytes from x */
+/*#define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
+
+// used everywhere in blenkernel and text.c
+void *copy_libblock(void *rt)
+{
+ ID *idn, *id;
+ ListBase *lb;
+ char *cp, *cpn;
+ int idn_len;
+
+ id= rt;
+
+ lb= wich_libbase(G.main, GS(id->name));
+ idn= alloc_libblock(lb, GS(id->name), id->name+2);
+
+ idn_len= MEM_allocN_len(idn);
+ if(idn_len - sizeof(ID) > 0) {
+ cp= (char *)id;
+ cpn= (char *)idn;
+ memcpy(cpn+sizeof(ID), cp+sizeof(ID), idn_len - sizeof(ID));
+ }
+
+ id->newid= idn;
+ idn->flag |= LIB_NEW;
+
+ return idn;
+}
+
+static void free_library(Library *lib)
+{
+ /* no freeing needed for libraries yet */
+}
+
+// used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c
+void free_libblock(ListBase *lb, void *idv)
+{
+ ID *id= idv;
+
+ switch( GS(id->name) ) { /* GetShort uit util.h */
+ case ID_SCE:
+ free_scene((Scene *)id);
+ break;
+ case ID_LI:
+ free_library((Library *)id);
+ break;
+ case ID_OB:
+ free_object((Object *)id);
+ break;
+ case ID_ME:
+ free_mesh((Mesh *)id);
+ break;
+ case ID_CU:
+ free_curve((Curve *)id);
+ break;
+ case ID_MB:
+ free_mball((MetaBall *)id);
+ break;
+ case ID_MA:
+ free_material((Material *)id);
+ break;
+ case ID_TE:
+ free_texture((Tex *)id);
+ break;
+ case ID_IM:
+ free_image((Image *)id);
+ break;
+ case ID_IK:
+ free_ika((Ika *)id);
+ break;
+ case ID_WV:
+ /* free_wave(id); */
+ break;
+ case ID_LT:
+ free_lattice((Lattice *)id);
+ break;
+ case ID_LA:
+ free_lamp((Lamp *)id);
+ break;
+ case ID_CA:
+/* free_camera(id); */
+ /* cast wasn't here before... spooky... */
+ free_camera((Camera*) id);
+ break;
+ case ID_IP:
+ free_ipo((Ipo *)id);
+ break;
+ case ID_KE:
+ free_key((Key *)id);
+ break;
+ case ID_WO:
+ free_world((World *)id);
+ break;
+ case ID_SCR:
+ free_screen((bScreen *)id);
+ break;
+ case ID_VF:
+ free_vfont((VFont *)id);
+ break;
+ case ID_TXT:
+ free_text((Text *)id);
+ break;
+ case ID_SO:
+ sound_free_sound((bSound *)id);
+ break;
+ case ID_SAMPLE:
+ sound_free_sample((bSample *)id);
+ break;
+ case ID_GR:
+ free_group((Group *)id);
+ break;
+ case ID_AR:
+ free_armature((bArmature *)id);
+ break;
+ case ID_AC:
+ free_action((bAction *)id);
+ break;
+ }
+
+ BLI_remlink(lb, id);
+ MEM_freeN(id);
+
+ /* should not be here!! this is an interface-thing */
+ allspace(OOPS_TEST, 0);
+}
+
+void free_libblock_us(ListBase *lb, void *idv) /* test users */
+{
+ ID *id= idv;
+
+ id->us--;
+
+ if(id->us<0) {
+ if(id->lib) printf("ERROR block %s %s users %d\n", id->lib->name, id->name, id->us);
+ else printf("ERROR block %s users %d\n", id->name, id->us);
+ }
+ if(id->us==0) {
+ if( GS(id->name)==ID_OB ) unlink_object((Object *)id);
+
+ free_libblock(lb, id);
+ }
+}
+
+
+void free_main(Main *mainvar)
+{
+ /* ook aanroepen bij file inlezen, erase all, etc */
+ ListBase *lbarray[MAX_LIBARRAY];
+ int a;
+
+ a= set_listbasepointers(mainvar, lbarray);
+ while(a--) {
+ ListBase *lb= lbarray[a];
+ ID *id;
+
+ while (id= lb->first) {
+ free_libblock(lb, id);
+ }
+ }
+
+ MEM_freeN(mainvar);
+}
+
+/* ***************** ID ************************ */
+
+// only used in exotic.c
+ID *find_id(char *type, char *name) /* type: "OB" of "MA" etc */
+{
+ ID *id;
+ ListBase *lb;
+
+ lb= wich_libbase(G.main, GS(type));
+
+ id= lb->first;
+ while(id) {
+ if( strcmp(id->name+2, name)==0 ) return id;
+ id= id->next;
+ }
+ return 0;
+}
+
+static void get_flags_for_id(ID *id, char *buf) {
+ int isfake= id->flag & LIB_FAKEUSER;
+
+ /* Writeout the flags for the entry, note there
+ * is a small hack that writes 5 spaces instead
+ * of 4 if no flags are displayed... this makes
+ * things usually line up ok - better would be
+ * to have that explicit, oh well - zr
+ */
+
+ if (id->us<0)
+ sprintf(buf, "-1W ");
+ else if (!id->lib && !isfake && id->us)
+ sprintf(buf, " ");
+ else
+ sprintf(buf, "%c%c%c ", id->lib?'L':' ', isfake?'F':' ', (id->us==0)?'O':' ');
+}
+
+static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr)
+{
+ int i, nids= BLI_countlist(lb);
+
+ *nr= -1;
+
+ if (nids>MAX_IDPUP) {
+ BLI_dynstr_append(pupds, "DataBrowse %x-2");
+ } else {
+ ID *id;
+
+ for (i=0, id= lb->first; id; id= id->next, i++) {
+ char buf[32];
+
+ if (id==link)
+ *nr= i+1;
+
+ get_flags_for_id(id, buf);
+
+ BLI_dynstr_append(pupds, buf);
+ BLI_dynstr_append(pupds, id->name+2);
+
+ if(id->next)
+ BLI_dynstr_append(pupds, "|");
+ }
+ }
+}
+
+ /* Silly routine, the only difference between the one
+ * above is that it only adds items with a matching
+ * blocktype... this should be unified somehow... - zr
+ */
+static void IPOnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr, int blocktype)
+{
+ ID *id;
+ int i, nids;
+
+ for (id= lb->first, nids= 0; id; id= id->next) {
+ Ipo *ipo= (Ipo*) id;
+
+ if (ipo->blocktype==blocktype)
+ nids++;
+ }
+
+ if (nids>MAX_IDPUP) {
+ BLI_dynstr_append(pupds, "DataBrowse %x-2");
+ } else {
+ for (i=0, id= lb->first; id; id= id->next) {
+ Ipo *ipo= (Ipo*) id;
+
+ if (ipo->blocktype==blocktype) {
+ char buf[32];
+
+ if (id==link)
+ *nr= i+1;
+
+ get_flags_for_id(id, buf);
+
+ BLI_dynstr_append(pupds, buf);
+ BLI_dynstr_append(pupds, id->name+2);
+
+ if(id->next)
+ BLI_dynstr_append(pupds, "|");
+
+ i++;
+ }
+ }
+ }
+}
+
+// used by headerbuttons.c buttons.c editobject.c editseq.c
+void IDnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr)
+{
+ DynStr *pupds= BLI_dynstr_new();
+
+ if (title) {
+ BLI_dynstr_append(pupds, title);
+ BLI_dynstr_append(pupds, "%t|");
+ }
+
+ IDnames_to_dyn_pupstring(pupds, lb, link, nr);
+
+ if (extraops) {
+ if (BLI_dynstr_get_len(pupds))
+ BLI_dynstr_append(pupds, "|");
+ BLI_dynstr_append(pupds, extraops);
+ }
+
+ *str= BLI_dynstr_get_cstring(pupds);
+ BLI_dynstr_free(pupds);
+}
+
+// only used by headerbuttons.c
+void IPOnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr, int blocktype)
+{
+ DynStr *pupds= BLI_dynstr_new();
+
+ if (title) {
+ BLI_dynstr_append(pupds, title);
+ BLI_dynstr_append(pupds, "%t|");
+ }
+
+ IPOnames_to_dyn_pupstring(pupds, lb, link, nr, blocktype);
+
+ if (extraops) {
+ if (BLI_dynstr_get_len(pupds))
+ BLI_dynstr_append(pupds, "|");
+ BLI_dynstr_append(pupds, extraops);
+ }
+
+ *str= BLI_dynstr_get_cstring(pupds);
+ BLI_dynstr_free(pupds);
+}
+
+// used by buttons.c library.c mball.c
+void splitIDname(char *name, char *left, int *nr)
+{
+ int a;
+
+ *nr= 0;
+ strncpy(left, name, 21);
+
+ a= strlen(name);
+ if(a>1 && name[a-1]=='.') return;
+
+ while(a--) {
+ if( name[a]=='.' ) {
+ left[a]= 0;
+ *nr= atol(name+a+1);
+ return;
+ }
+ if( isdigit(name[a])==0 ) break;
+
+ left[a]= 0;
+ }
+ strcpy(left, name);
+}
+
+static void sort_alpha_id(ListBase *lb, ID *id)
+{
+ ID *idtest;
+
+ /* alfabetisch opnieuw invoegen */
+ if(lb->first!=lb->last) {
+ BLI_remlink(lb, id);
+
+ idtest= lb->first;
+ while(idtest) {
+ if(strcasecmp(idtest->name, id->name)>0 || idtest->lib) {
+ BLI_insertlinkbefore(lb, idtest, id);
+ break;
+ }
+ idtest= idtest->next;
+ }
+ /* als laatste */
+ if(idtest==0) {
+ BLI_addtail(lb, id);
+ }
+ }
+
+}
+
+int new_id(ListBase *lb, ID *id, char *tname)
+/* alleen locale blokken: externe en indirekte hebben al een unieke ID */
+/* return 1: nieuwe naam gemaakt */
+{
+ ID *idtest;
+ int nr= 0, nrtest, maxtest=32, a;
+ char aname[32], *name, left[24], leftest[24], in_use[32];
+
+ /* - naam splitsen
+ * - zoeken
+ */
+
+ if(id->lib) return 0;
+
+ if(tname==0) name= id->name+2;
+ else {
+ /* tname can be const */
+ strncpy(aname, tname, 21);
+ name= aname;
+
+ if( strlen(name) > 21 ) name[21]= 0;
+ }
+
+ if(lb==0) lb= wich_libbase(G.main, GS(id->name));
+
+ /* eerste fase: bestaat de id al? */
+ idtest= lb->first;
+ while(idtest) {
+
+ if(id!=idtest && idtest->lib==0) {
+
+ /* niet alphabetic testen! */
+ /* optim */
+ if( idtest->name[2] == name[0] ) {
+ if(strcmp(name, idtest->name+2)==0) break;
+ }
+ }
+
+ idtest= idtest->next;
+ }
+
+ /* if there is no double return */
+ if(idtest==0) {
+ strcpy(id->name+2, name);
+ return 0;
+ }
+
+ memset(in_use, 0, maxtest);
+
+ splitIDname(name, left, &nr);
+ if(nr>999 && strlen(left)>16) left[16]= 0;
+ else if(strlen(left)>17) left[17]= 0;
+
+
+ idtest= lb->first;
+ while(idtest) {
+
+ if(id!=idtest && idtest->lib==0) {
+
+ splitIDname(idtest->name+2, leftest, &nrtest);
+ if(strcmp(left, leftest)==0) {
+
+ if(nrtest<maxtest) in_use[nrtest]= 1;
+ if(nr <= nrtest) nr= nrtest+1;
+ }
+ }
+
+ idtest= idtest->next;
+ }
+
+ for(a=0; a<maxtest; a++) {
+ if(a>=nr) break;
+ if( in_use[a]==0 ) {
+ nr= a;
+ break;
+ }
+ }
+
+ if(nr==0) sprintf(id->name+2, "%s", left);
+ else {
+ if (nr >= 1000 && strlen(left) > 16) {
+ // this would overflow name buffer
+ left[16]= 0;
+ return (new_id(lb, id, left));
+ }
+ /* this format specifier is fucked... */
+ sprintf(id->name+2, "%s.%0.3d", left, nr);
+ }
+
+ sort_alpha_id(lb, id);
+
+ return 1;
+}
+
+// next to indirect usage in read/writefile also in editobject.c scene.c
+void clear_id_newpoins()
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ ID *id;
+ int a;
+
+ a= set_listbasepointers(G.main, lbarray);
+ while(a--) {
+ id= lbarray[a]->first;
+ while(id) {
+ id->newid= 0;
+ id->flag &= ~LIB_NEW;
+ id= id->next;
+ }
+ }
+}
+
+void all_local(void)
+{
+ ListBase *lbarray[MAX_LIBARRAY], tempbase={0, 0};
+ ID *id, *idn;
+ int a;
+
+ a= set_listbasepointers(G.main, lbarray);
+ while(a--) {
+ id= lbarray[a]->first;
+
+ while(id) {
+ id->newid= 0;
+ id->flag &= ~(LIB_EXTERN|LIB_INDIRECT|LIB_NEW);
+
+ idn= id->next; /* id wordt mogelijk opnieuw ingevoegd */
+ if(id->lib) {
+ id->lib= 0;
+ new_id(lbarray[a], id, 0); /* new_id doet dit alleen bij dubbele namen */
+ sort_alpha_id(lbarray[a], id);
+ }
+ else {
+ /* patch: testen of de zaak wel alphabetisch is */
+/*
+ if(idn) {
+ if(strcasecmp(id->name, idn->name)>0) {
+ remlink(lbarray[a], id);
+ addtail(&tempbase, id);
+ }
+ else if(id->prev) {
+ idp= id->prev;
+ if(strcasecmp(idp->name, id->name)>0) {
+ remlink(lbarray[a], id);
+ addtail(&tempbase, id);
+ }
+ }
+ }
+*/
+ }
+
+ id= idn;
+ }
+
+ /* patch2: zorgen dat de zaak wel alphabetisch is */
+ while( (id=tempbase.first) ) {
+ BLI_remlink(&tempbase, id);
+ BLI_addtail(lbarray[a], id);
+ new_id(lbarray[a], id, 0);
+ }
+ }
+}
+
+
+void test_idbutton(char *name)
+{
+ /* vanuit buttons: als naam al bestaat: new_id aanroepen */
+ ListBase *lb;
+ ID *idtest;
+
+
+ lb= wich_libbase(G.main, GS(name-2) );
+ if(lb==0) return;
+
+ /* zoek welke id */
+ idtest= lb->first;
+ while(idtest) {
+ if( strcmp(idtest->name+2, name)==0) break;
+ idtest= idtest->next;
+ }
+
+ if(idtest) if( new_id(lb, idtest, name)==0 ) sort_alpha_id(lb, idtest);
+}
+
+void rename_id(ID *id, char *name)
+{
+ ListBase *lb;
+
+ strncpy(id->name+2, name, 21);
+ lb= wich_libbase(G.main, GS(id->name) );
+
+ new_id(lb, id, name);
+}
+
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
new file mode 100644
index 00000000000..71d0e95031d
--- /dev/null
+++ b/source/blender/blenkernel/intern/material.c
@@ -0,0 +1,747 @@
+
+/* material.c MIX MODEL
+ *
+ * maart 95
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include "MEM_guardedalloc.h"
+
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BKE_mesh.h"
+#include "BKE_library.h"
+#include "BKE_displist.h"
+#include "BPY_extern.h"
+#include "BKE_material.h"
+
+void free_material(Material *ma)
+{
+ int a;
+ MTex *mtex;
+
+ BPY_free_scriptlink(&ma->scriptlink);
+
+ if(ma->ren) MEM_freeN(ma->ren);
+ ma->ren= 0;
+
+ for(a=0; a<8; a++) {
+ mtex= ma->mtex[a];
+ if(mtex && mtex->tex) mtex->tex->id.us--;
+ if(mtex) MEM_freeN(mtex);
+ }
+}
+
+void init_material(Material *ma)
+{
+ ma->lay= 1;
+ ma->r= ma->g= ma->b= ma->ref= 0.8f;
+ ma->specr= ma->specg= ma->specb= 1.0f;
+ ma->mirr= ma->mirg= ma->mirb= 1.0f;
+ ma->amb= 0.5f;
+ ma->alpha= 1.0f;
+ ma->spec= ma->hasize= 0.5f;
+ ma->har= 50;
+ ma->starc= ma->ringc= 4;
+ ma->linec= 12;
+ ma->flarec= 1;
+ ma->flaresize= ma->subsize= 1.0f;
+ ma->friction= 0.5f;
+
+ ma->mode= MA_TRACEBLE+MA_SHADOW;
+}
+
+Material *add_material(char *name)
+{
+ Material *ma;
+
+ ma= alloc_libblock(&G.main->mat, ID_MA, name);
+
+ init_material(ma);
+
+ return ma;
+}
+
+Material *copy_material(Material *ma)
+{
+ Material *man;
+ int a;
+
+ man= copy_libblock(ma);
+
+ id_us_plus((ID *)man->ipo);
+
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a]) {
+ man->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial");
+ memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex));
+ id_us_plus((ID *)man->mtex[a]->tex);
+ }
+ }
+
+ BPY_copy_scriptlink(&ma->scriptlink);
+
+ return man;
+}
+
+void make_local_material(Material *ma)
+{
+ Object *ob;
+ Mesh *me;
+ Curve *cu;
+ MetaBall *mb;
+ Material *man;
+ int a, local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(ma->id.lib==0) return;
+ if(ma->id.us==1) {
+ ma->id.lib= 0;
+ ma->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ma, 0);
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a]) id_lib_extern((ID *)ma->mtex[a]->tex);
+ }
+
+ return;
+ }
+
+ /* test objects */
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->mat) {
+ for(a=0; a<ob->totcol; a++) {
+ if(ob->mat[a]==ma) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ }
+ }
+ ob= ob->id.next;
+ }
+ /* test meshes */
+ me= G.main->mesh.first;
+ while(me) {
+ if(me->mat) {
+ for(a=0; a<me->totcol; a++) {
+ if(me->mat[a]==ma) {
+ if(me->id.lib) lib= 1;
+ else local= 1;
+ }
+ }
+ }
+ me= me->id.next;
+ }
+ /* test curves */
+ cu= G.main->curve.first;
+ while(cu) {
+ if(cu->mat) {
+ for(a=0; a<cu->totcol; a++) {
+ if(cu->mat[a]==ma) {
+ if(cu->id.lib) lib= 1;
+ else local= 1;
+ }
+ }
+ }
+ cu= cu->id.next;
+ }
+ /* test mballs */
+ mb= G.main->mball.first;
+ while(mb) {
+ if(mb->mat) {
+ for(a=0; a<mb->totcol; a++) {
+ if(mb->mat[a]==ma) {
+ if(mb->id.lib) lib= 1;
+ else local= 1;
+ }
+ }
+ }
+ mb= mb->id.next;
+ }
+
+ if(local && lib==0) {
+ ma->id.lib= 0;
+ ma->id.flag= LIB_LOCAL;
+
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a]) id_lib_extern((ID *)ma->mtex[a]->tex);
+ }
+
+ new_id(0, (ID *)ma, 0);
+ }
+ else if(local && lib) {
+ man= copy_material(ma);
+ man->id.us= 0;
+
+ /* do objects */
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->mat) {
+ for(a=0; a<ob->totcol; a++) {
+ if(ob->mat[a]==ma) {
+ if(ob->id.lib==0) {
+ ob->mat[a]= man;
+ man->id.us++;
+ ma->id.us--;
+ }
+ }
+ }
+ }
+ ob= ob->id.next;
+ }
+ /* do meshes */
+ me= G.main->mesh.first;
+ while(me) {
+ if(me->mat) {
+ for(a=0; a<me->totcol; a++) {
+ if(me->mat[a]==ma) {
+ if(me->id.lib==0) {
+ me->mat[a]= man;
+ man->id.us++;
+ ma->id.us--;
+ }
+ }
+ }
+ }
+ me= me->id.next;
+ }
+ /* do curves */
+ cu= G.main->curve.first;
+ while(cu) {
+ if(cu->mat) {
+ for(a=0; a<cu->totcol; a++) {
+ if(cu->mat[a]==ma) {
+ if(cu->id.lib==0) {
+ cu->mat[a]= man;
+ man->id.us++;
+ ma->id.us--;
+ }
+ }
+ }
+ }
+ cu= cu->id.next;
+ }
+ /* do mballs */
+ mb= G.main->mball.first;
+ while(mb) {
+ if(mb->mat) {
+ for(a=0; a<mb->totcol; a++) {
+ if(mb->mat[a]==ma) {
+ if(mb->id.lib==0) {
+ mb->mat[a]= man;
+ man->id.us++;
+ ma->id.us--;
+ }
+ }
+ }
+ }
+ mb= mb->id.next;
+ }
+ }
+}
+
+Material ***give_matarar(Object *ob)
+{
+ Mesh *me;
+ Curve *cu;
+ MetaBall *mb;
+
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+ return &(me->mat);
+ }
+ else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) {
+ cu= ob->data;
+ return &(cu->mat);
+ }
+ else if(ob->type==OB_MBALL) {
+ mb= ob->data;
+ return &(mb->mat);
+ }
+ return 0;
+}
+
+short *give_totcolp(Object *ob)
+{
+ Mesh *me;
+ Curve *cu;
+ MetaBall *mb;
+
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+ return &(me->totcol);
+ }
+ else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) {
+ cu= ob->data;
+ return &(cu->totcol);
+ }
+ else if(ob->type==OB_MBALL) {
+ mb= ob->data;
+ return &(mb->totcol);
+ }
+ return 0;
+}
+
+Material *give_current_material(Object *ob, int act)
+{
+ Material ***matarar, *ma;
+
+ if(ob==0) return 0;
+ if(ob->totcol==0) return 0;
+
+ if(act>ob->totcol) act= ob->totcol;
+ else if(act==0) act= 1;
+
+ if( BTST(ob->colbits, act-1) ) { /* aan object */
+ ma= ob->mat[act-1];
+ }
+ else { /* aan data */
+ matarar= give_matarar(ob);
+
+ if(matarar && *matarar) ma= (*matarar)[act-1];
+ else ma= 0;
+
+ }
+
+ return ma;
+}
+
+ID *material_from(Object *ob, int act)
+{
+
+ if(ob==0) return 0;
+
+ if(ob->totcol==0) return ob->data;
+ if(act==0) act= 1;
+
+ if( BTST(ob->colbits, act-1) ) return (ID *)ob;
+ else return ob->data;
+}
+
+/* GS reads the memory pointed at in a specific ordering. There are,
+ * however two definitions for it. I have jotted them down here, both,
+ * but I think the first one is actually used. The thing is that
+ * big-endian systems might read this the wrong way round. OTOH, we
+ * constructed the IDs that are read out with this macro explicitly as
+ * well. I expect we'll sort it out soon... */
+
+/* from blendef: */
+#define GS(a) (*((short *)(a)))
+
+/* from misc_util: flip the bytes from x */
+/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
+
+void test_object_materials(ID *id)
+{
+ /* ob mat-array evenlang maken als obdata mat-array */
+ Object *ob;
+ Mesh *me;
+ Curve *cu;
+ MetaBall *mb;
+ Material **newmatar;
+ int totcol=0;
+
+ if(id==0) return;
+
+ if( GS(id->name)==ID_ME ) {
+ me= (Mesh *)id;
+ totcol= me->totcol;
+ }
+ else if( GS(id->name)==ID_CU ) {
+ cu= (Curve *)id;
+ totcol= cu->totcol;
+ }
+ else if( GS(id->name)==ID_MB ) {
+ mb= (MetaBall *)id;
+ totcol= mb->totcol;
+ }
+ else return;
+
+ ob= G.main->object.first;
+ while(ob) {
+
+ if(ob->data==id) {
+
+ if(totcol==0) {
+ if(ob->totcol) {
+ MEM_freeN(ob->mat);
+ ob->mat= 0;
+ }
+ }
+ else if(ob->totcol<totcol) {
+ newmatar= MEM_callocN(sizeof(void *)*totcol, "newmatar");
+ if(ob->totcol) {
+ memcpy(newmatar, ob->mat, sizeof(void *)*ob->totcol);
+ MEM_freeN(ob->mat);
+ }
+ ob->mat= newmatar;
+ }
+ ob->totcol= totcol;
+ if(ob->totcol && ob->actcol==0) ob->actcol= 1;
+ if(ob->actcol>ob->totcol) ob->actcol= ob->totcol;
+ }
+ ob= ob->id.next;
+ }
+}
+
+
+void assign_material(Object *ob, Material *ma, int act)
+{
+ Material *mao, **matar, ***matarar;
+ short *totcolp;
+
+ if(act>MAXMAT) return;
+ if(act<1) act= 1;
+
+ /* test arraylens */
+
+ totcolp= give_totcolp(ob);
+ matarar= give_matarar(ob);
+
+ if(totcolp==0 || matarar==0) return;
+
+ if( act > *totcolp) {
+ matar= MEM_callocN(sizeof(void *)*act, "matarray1");
+ if( *totcolp) {
+ memcpy(matar, *matarar, sizeof(void *)*( *totcolp ));
+ MEM_freeN(*matarar);
+ }
+ *matarar= matar;
+ *totcolp= act;
+ }
+
+ if(act > ob->totcol) {
+ matar= MEM_callocN(sizeof(void *)*act, "matarray2");
+ if( ob->totcol) {
+ memcpy(matar, ob->mat, sizeof(void *)*( ob->totcol ));
+ MEM_freeN(ob->mat);
+ }
+ ob->mat= matar;
+ ob->totcol= act;
+ }
+
+ /* doe 't */
+
+ if( BTST(ob->colbits, act-1) ) { /* aan object */
+ mao= ob->mat[act-1];
+ if(mao) mao->id.us--;
+ ob->mat[act-1]= ma;
+ }
+ else { /* aan data */
+ mao= (*matarar)[act-1];
+ if(mao) mao->id.us--;
+ (*matarar)[act-1]= ma;
+ }
+ id_us_plus((ID *)ma);
+ test_object_materials(ob->data);
+}
+
+void new_material_to_objectdata(Object *ob)
+{
+ Material *ma;
+
+ if(ob==0) return;
+ if(ob->totcol>=MAXMAT) return;
+
+ ma= give_current_material(ob, ob->actcol);
+ if(ma==0) {
+ ma= add_material("Material");
+ ma->id.us= 0;
+ }
+
+ if(ob->actcol) {
+ if( BTST(ob->colbits, ob->actcol-1) ) {
+ ob->colbits= BSET(ob->colbits, ob->totcol);
+ }
+ }
+
+ assign_material(ob, ma, ob->totcol+1);
+ ob->actcol= ob->totcol;
+}
+
+
+void init_render_material(Material *ma)
+{
+ MTex *mtex;
+ int a, needuv=0;
+
+ if(ma->ren) return;
+
+ if(ma->flarec==0) ma->flarec= 1;
+
+ ma->ren= MEM_mallocN(sizeof(Material), "initrendermaterial");
+ memcpy(ma->ren, ma, sizeof(Material));
+
+ /* alle texcoflags van mtex adden */
+ ma= ma->ren;
+ ma->texco= 0;
+ ma->mapto= 0;
+ for(a=0; a<8; a++) {
+ mtex= ma->mtex[a];
+ if(mtex && mtex->tex) {
+
+ /* force std. ref mapping for envmap */
+ if(mtex->tex->type==TEX_ENVMAP) {
+/* mtex->texco= TEXCO_REFL; */
+/* mtex->projx= PROJ_X; */
+/* mtex->projy= PROJ_Y; */
+/* mtex->projz= PROJ_Z; */
+/* mtex->mapping= MTEX_FLAT; */
+ }
+ /* hier niet testen op mtex->object en mtex->texco op TEXCO_ORCO zetten: mtex is linked! */
+
+ ma->texco |= mtex->texco;
+ ma->mapto |= mtex->mapto;
+ if(R.osa) {
+ if ELEM3(mtex->tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) ma->texco |= TEXCO_OSA;
+ }
+
+ if(ma->texco & (511)) needuv= 1;
+
+ if(mtex->object) mtex->object->flag |= OB_DO_IMAT;
+
+ }
+ }
+ if(ma->mode & MA_ZTRA) {
+ /* if(ma->alpha==0.0 || ma->alpha==1.0) */
+ R.flag |= R_ZTRA;
+ }
+ if(ma->mode & MA_VERTEXCOLP) ma->mode |= MA_VERTEXCOL;
+
+ if(ma->mode & (MA_VERTEXCOL|MA_FACETEXTURE)) {
+ needuv= 1;
+ if(R.osa) ma->texco |= TEXCO_OSA; /* for texfaces */
+ }
+ if(needuv) ma->texco |= NEED_UV;
+
+ ma->ambr= ma->amb*R.wrld.ambr;
+ ma->ambg= ma->amb*R.wrld.ambg;
+ ma->ambb= ma->amb*R.wrld.ambb;
+
+}
+
+void init_render_materials()
+{
+ Material *ma;
+
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->id.us) init_render_material(ma);
+ ma= ma->id.next;
+ }
+
+}
+
+void end_render_material(Material *ma)
+{
+
+ if(ma->ren) MEM_freeN(ma->ren);
+ ma->ren= 0;
+
+ if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
+ if( !(ma->mode & MA_HALO) ) {
+ ma->r= ma->g= ma->b= 1.0;
+ }
+ }
+}
+
+void end_render_materials()
+{
+ Material *ma;
+
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->id.us) end_render_material(ma);
+ ma= ma->id.next;
+ }
+
+}
+
+
+/* ****************** */
+
+char colname_array[125][20]= {
+"Black","DarkRed","HalveRed","Red","Red",
+"DarkGreen","DarkOlive","Brown","Chocolate","OrangeRed",
+"HalveGreen","GreenOlive","DryOlive","Goldenrod","DarkOrange",
+"LightGreen","Chartreuse","YellowGreen","Yellow","Gold",
+"Green","LawnGreen","GreenYellow","LightOlive","Yellow",
+"DarkBlue","DarkPurple","HotPink","VioletPink","RedPink",
+"SlateGray","DarkGrey","PalePurple","IndianRed","Tomato",
+"SeaGreen","PaleGreen","GreenKhaki","LightBrown","LightSalmon",
+"SpringGreen","PaleGreen","MediumOlive","YellowBrown","LightGold",
+"LightGreen","LightGreen","LightGreen","GreenYellow","PaleYellow",
+"HalveBlue","DarkSky","HalveMagenta","VioletRed","DeepPink",
+"SteelBlue","SkyBlue","Orchid","LightHotPink","HotPink",
+"SeaGreen","SlateGray","MediumGrey","Burlywood","LightPink",
+"SpringGreen","Aquamarine","PaleGreen","Khaki","PaleOrange",
+"SpringGreen","SeaGreen","PaleGreen","PaleWhite","YellowWhite",
+"LightBlue","Purple","MediumOrchid","Magenta","Magenta",
+"RoyalBlue","SlateBlue","MediumOrchid","Orchid","Magenta",
+"DeepSkyBlue","LightSteelBlue","LightSkyBlue","Violet","LightPink",
+"Cyaan","DarkTurquoise","SkyBlue","Grey","Snow",
+"Mint","Mint","Aquamarine","MintCream","Ivory",
+"Blue","Blue","DarkMagenta","DarkOrchid","Magenta",
+"SkyBlue","RoyalBlue","LightSlateBlue","MediumOrchid","Magenta",
+"DodgerBlue","SteelBlue","MediumPurple","PalePurple","Plum",
+"DeepSkyBlue","PaleBlue","LightSkyBlue","PalePurple","Thistle",
+"Cyan","ColdBlue","PaleTurquoise","GhostWhite","White"
+};
+
+void automatname(Material *ma)
+{
+ int nr, r, g, b;
+ float ref;
+
+ if(ma==0) return;
+ if(ma->mode & MA_SHLESS) ref= 1.0;
+ else ref= ma->ref;
+
+ r= (int)(4.99*(ref*ma->r));
+ g= (int)(4.99*(ref*ma->g));
+ b= (int)(4.99*(ref*ma->b));
+ nr= r + 5*g + 25*b;
+ if(nr>124) nr= 124;
+ new_id(&G.main->mat, (ID *)ma, colname_array[nr]);
+
+}
+
+
+void delete_material_index()
+{
+ Material *mao, ***matarar;
+ Object *ob, *obt;
+ Mesh *me;
+ Curve *cu;
+ Nurb *nu;
+ MFace *mface;
+ short *totcolp;
+ int a, actcol;
+
+ if(G.obedit) {
+ error("Unable to perform function in EditMode");
+ return;
+ }
+ ob= ((G.scene->basact)? (G.scene->basact->object) : 0) ;
+ if(ob==0 || ob->totcol==0) return;
+
+ /* neem als uitgangspunt de mesh/curve/mball, verwijder 1 index, EN bij alle ob's
+ * die ook zelfde ob->data hebben
+ *
+ * Daarna ook indexen in mesh/curve/mball wijzigen!!!
+ */
+
+ totcolp= give_totcolp(ob);
+ matarar= give_matarar(ob);
+
+ /* we deleten de actcol */
+ if(ob->totcol) {
+ mao= (*matarar)[ob->actcol-1];
+ if(mao) mao->id.us--;
+ }
+
+ for(a=ob->actcol; a<ob->totcol; a++) {
+ (*matarar)[a-1]= (*matarar)[a];
+ }
+ (*totcolp)--;
+
+ if(*totcolp==0) {
+ MEM_freeN(*matarar);
+ *matarar= 0;
+ }
+
+ actcol= ob->actcol;
+ obt= G.main->object.first;
+ while(obt) {
+
+ if(obt->data==ob->data) {
+
+ /* LET OP: actcol hier niet van ob of van obt pakken (kan nul worden) */
+ mao= obt->mat[actcol-1];
+ if(mao) mao->id.us--;
+
+ for(a=actcol; a<obt->totcol; a++) obt->mat[a-1]= obt->mat[a];
+ obt->totcol--;
+ if(obt->actcol > obt->totcol) obt->actcol= obt->totcol;
+
+ if(obt->totcol==0) {
+ MEM_freeN(obt->mat);
+ obt->mat= 0;
+ }
+ }
+ obt= obt->id.next;
+ }
+ allqueue(REDRAWBUTSMAT, 0);
+
+
+ /* indexen van mesh goedzetten */
+
+ if(ob->type==OB_MESH) {
+ me= get_mesh(ob);
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+ if(mface->mat_nr && mface->mat_nr>=actcol-1) mface->mat_nr--;
+ mface++;
+ }
+ makeDispList(ob);
+ }
+ else if ELEM(ob->type, OB_CURVE, OB_SURF) {
+ cu= ob->data;
+ nu= cu->nurb.first;
+
+ while(nu) {
+ if(nu->mat_nr && nu->mat_nr>=actcol-1) nu->mat_nr--;
+ nu= nu->next;
+ }
+ makeDispList(ob);
+ }
+}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
new file mode 100644
index 00000000000..9f09191f9d2
--- /dev/null
+++ b/source/blender/blenkernel/intern/mball.c
@@ -0,0 +1,1540 @@
+/* mball.c MIXED MODEL
+ *
+ * mei 95
+ *
+ *
+ *
+ * METABALLS ontstaan vanuit een Object (naam zonder nr), hier zit de DispList en boundbox,
+ * alle objecten met zelfde naam (en een nr) worden hieraan toegevoegd.
+ *
+ * De texture coordinaten zitten als loos element in de displist.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include "MEM_guardedalloc.h"
+
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_mesh_types.h"
+
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_bad_level_calls.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+/* #include "BKE_object.h" */
+#include "BKE_scene.h"
+#include "BKE_blender.h"
+#include "BKE_library.h"
+#include "BKE_displist.h"
+#include "BKE_mball.h"
+
+/* Functions */
+
+
+
+void unlink_mball(MetaBall *mb)
+{
+ int a;
+
+ for(a=0; a<mb->totcol; a++) {
+ if(mb->mat[a]) mb->mat[a]->id.us--;
+ mb->mat[a]= 0;
+ }
+
+
+}
+
+
+/* niet mball zelf vrijgeven */
+void free_mball(MetaBall *mb)
+{
+
+ unlink_mball(mb);
+
+ if(mb->mat) MEM_freeN(mb->mat);
+ if(mb->bb) MEM_freeN(mb->bb);
+ BLI_freelistN(&mb->elems);
+ if(mb->disp.first) freedisplist(&mb->disp);
+}
+
+MetaBall *add_mball()
+{
+ MetaBall *mb;
+
+ mb= alloc_libblock(&G.main->mball, ID_MB, "Meta");
+
+ mb->size[0]= mb->size[1]= mb->size[2]= 1.0;
+ mb->texflag= AUTOSPACE;
+
+ mb->wiresize= 0.4f;
+ mb->rendersize= 0.2f;
+ mb->thresh= 0.6f;
+
+ return mb;
+}
+
+MetaBall *copy_mball(MetaBall *mb)
+{
+ MetaBall *mbn;
+ int a;
+
+ mbn= copy_libblock(mb);
+
+ duplicatelist(&mbn->elems, &mb->elems);
+
+ mbn->mat= MEM_dupallocN(mb->mat);
+ for(a=0; a<mbn->totcol; a++) {
+ id_us_plus((ID *)mbn->mat[a]);
+ }
+ mbn->bb= MEM_dupallocN(mb->bb);
+
+ return mbn;
+}
+
+void make_local_mball(MetaBall *mb)
+{
+ Object *ob;
+ MetaBall *mbn;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(mb->id.lib==0) return;
+ if(mb->id.us==1) {
+ mb->id.lib= 0;
+ mb->id.flag= LIB_LOCAL;
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==mb) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ mb->id.lib= 0;
+ mb->id.flag= LIB_LOCAL;
+ }
+ else if(local && lib) {
+ mbn= copy_mball(mb);
+ mbn->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==mb) {
+
+ if(ob->id.lib==0) {
+ ob->data= mbn;
+ mbn->id.us++;
+ mb->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+
+void tex_space_mball(Object *ob)
+{
+ DispList *dl;
+ BoundBox *bb;
+ float *data, min[3], max[3], loc[3], size[3];
+ int tot, doit=0;
+
+ if(ob->bb==0) ob->bb= MEM_callocN(sizeof(BoundBox), "mb boundbox");
+ bb= ob->bb;
+
+ /* Weird one, this. */
+/* INIT_MINMAX(min, max); */
+ (min)[0]= (min)[1]= (min)[2]= 1.0e30f;
+ (max)[0]= (max)[1]= (max)[2]= -1.0e30f;
+
+ dl= ob->disp.first;
+ while(dl) {
+ tot= dl->nr;
+ if(tot) doit= 1;
+ data= dl->verts;
+ while(tot--) {
+ /* Also weird... but longer. From utildefines. */
+ DO_MINMAX(data, min, max);
+ data+= 3;
+ }
+ dl= dl->next;
+ }
+
+ if(doit) {
+ loc[0]= (min[0]+max[0])/2.0f;
+ loc[1]= (min[1]+max[1])/2.0f;
+ loc[2]= (min[2]+max[2])/2.0f;
+
+ size[0]= (max[0]-min[0])/2.0f;
+ size[1]= (max[1]-min[1])/2.0f;
+ size[2]= (max[2]-min[2])/2.0f;
+ }
+ else {
+ loc[0]= loc[1]= loc[2]= 0.0f;
+ size[0]= size[1]= size[2]= 1.0f;
+ }
+
+ bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= loc[0]-size[0];
+ bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= loc[0]+size[0];
+
+ bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= loc[1]-size[1];
+ bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= loc[1]+size[1];
+
+ bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= loc[2]-size[2];
+ bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= loc[2]+size[2];
+
+}
+
+void make_orco_mball(Object *ob)
+{
+ BoundBox *bb;
+ DispList *dl;
+ float *data;
+ float loc[3], size[3];
+ int a;
+
+ /* size en loc restoren */
+ bb= ob->bb;
+ loc[0]= (bb->vec[0][0]+bb->vec[4][0])/2.0f;
+ size[0]= bb->vec[4][0]-loc[0];
+ loc[1]= (bb->vec[0][1]+bb->vec[2][1])/2.0f;
+ size[1]= bb->vec[2][1]-loc[1];
+ loc[2]= (bb->vec[0][2]+bb->vec[1][2])/2.0f;
+ size[2]= bb->vec[1][2]-loc[2];
+
+ dl= ob->disp.first;
+ data= dl->verts;
+ a= dl->nr;
+ while(a--) {
+ data[0]= (data[0]-loc[0])/size[0];
+ data[1]= (data[1]-loc[1])/size[1];
+ data[2]= (data[2]-loc[2])/size[2];
+
+ data+= 3;
+ }
+}
+
+
+Object *find_basis_mball(Object *basis)
+{
+ Base *base;
+ int basisnr;
+ char basisname[32];
+
+ splitIDname(basis->id.name+2, basisname, &basisnr);
+
+ for (base= G.scene->base.first; base && basisnr; base= base->next) {
+ Object *ob= base->object;
+
+ if (ob!=basis && ob->type==OB_MBALL) {
+ char obname[32];
+ int obnr;
+
+ splitIDname(ob->id.name+2, obname, &obnr);
+
+ if ((strcmp(obname, basisname)==0) && obnr<basisnr) {
+ basis= ob;
+ basisnr= obnr;
+ }
+ }
+ }
+
+ return basis;
+}
+
+
+/* ******************** ARITH ************************* */
+
+/* DANKBAAR GEBRUIK GEMAAKT VAN (EN COMPLEET VERANDERD) :
+ * C code from the article
+ * "An Implicit Surface Polygonizer"
+ * by Jules Bloomenthal, jbloom@beauty.gmu.edu
+ * in "Graphics Gems IV", Academic Press, 1994
+
+ * Authored by Jules Bloomenthal, Xerox PARC.
+ * Copyright (c) Xerox Corporation, 1991. All rights reserved.
+ * Permission is granted to reproduce, use and distribute this code for
+ * any and all purposes, provided that this notice appears in all copies. */
+
+#define RES 12 /* # converge iterations */
+
+#define L 0 /* left direction: -x, -i */
+#define R 1 /* right direction: +x, +i */
+#define B 2 /* bottom direction: -y, -j */
+#define T 3 /* top direction: +y, +j */
+#define N 4 /* near direction: -z, -k */
+#define F 5 /* far direction: +z, +k */
+#define LBN 0 /* left bottom near corner */
+#define LBF 1 /* left bottom far corner */
+#define LTN 2 /* left top near corner */
+#define LTF 3 /* left top far corner */
+#define RBN 4 /* right bottom near corner */
+#define RBF 5 /* right bottom far corner */
+#define RTN 6 /* right top near corner */
+#define RTF 7 /* right top far corner */
+
+/* the LBN corner of cube (i, j, k), corresponds with location
+ * (start.x+(i-0.5)*size, start.y+(j-0.5)*size, start.z+(k-0.5)*size) */
+
+#define HASHBIT (5)
+#define HASHSIZE (size_t)(1<<(3*HASHBIT)) /* hash table size (32768) */
+
+#define HASH(i,j,k) ((((( (i) & 31)<<5) | ( (j) & 31))<<5 ) | ( (k) & 31) )
+
+#define MB_BIT(i, bit) (((i)>>(bit))&1)
+#define FLIP(i,bit) ((i)^1<<(bit)) /* flip the given bit of i */
+
+typedef struct point { /* a three-dimensional point */
+ float x, y, z; /* its coordinates */
+} MB_POINT;
+
+typedef struct vertex { /* surface vertex */
+ MB_POINT position, normal; /* position and surface normal */
+} VERTEX;
+
+typedef struct vertices { /* list of vertices in polygonization */
+ int count, max; /* # vertices, max # allowed */
+ VERTEX *ptr; /* dynamically allocated */
+} VERTICES;
+
+typedef struct corner { /* corner of a cube */
+ int i, j, k; /* (i, j, k) is index within lattice */
+ float x, y, z, value; /* location and function value */
+ struct corner *next;
+} CORNER;
+
+typedef struct cube { /* partitioning cell (cube) */
+ int i, j, k; /* lattice location of cube */
+ CORNER *corners[8]; /* eight corners */
+} CUBE;
+
+typedef struct cubes { /* linked list of cubes acting as stack */
+ CUBE cube; /* a single cube */
+ struct cubes *next; /* remaining elements */
+} CUBES;
+
+typedef struct centerlist { /* list of cube locations */
+ int i, j, k; /* cube location */
+ struct centerlist *next; /* remaining elements */
+} CENTERLIST;
+
+typedef struct edgelist { /* list of edges */
+ int i1, j1, k1, i2, j2, k2; /* edge corner ids */
+ int vid; /* vertex id */
+ struct edgelist *next; /* remaining elements */
+} EDGELIST;
+
+typedef struct intlist { /* list of integers */
+ int i; /* an integer */
+ struct intlist *next; /* remaining elements */
+} INTLIST;
+
+typedef struct intlists { /* list of list of integers */
+ INTLIST *list; /* a list of integers */
+ struct intlists *next; /* remaining elements */
+} INTLISTS;
+
+typedef struct process { /* parameters, function, storage */
+ /* what happens here? floats, I think. */
+ /* float (*function)(void); */ /* implicit surface function */
+ float (*function)(float, float, float);
+ float size, delta; /* cube size, normal delta */
+ int bounds; /* cube range within lattice */
+ MB_POINT start; /* start point on surface */
+ CUBES *cubes; /* active cubes */
+ VERTICES vertices; /* surface vertices */
+ CENTERLIST **centers; /* cube center hash table */
+ CORNER **corners; /* corner value hash table */
+ EDGELIST **edges; /* edge and vertex id hash table */
+} PROCESS;
+
+/* Some declarations are in order !!! */
+
+/* these should go into a header ! But the compiler doesn't like that,
+ * for some reason */
+
+void freepolygonize(PROCESS *p);
+void docube(CUBE *cube, PROCESS *p);
+void testface(int i, int j, int k, CUBE* old,
+ int bit, int c1, int c2, int c3, int c4, PROCESS *p);
+CORNER *setcorner (PROCESS* p, int i, int j, int k);
+int vertid (CORNER *c1, CORNER *c2, PROCESS *p);
+int setcenter(CENTERLIST *table[], int i, int j, int k);
+int otherface (int edge, int face);
+void makecubetable (void);
+void setedge (EDGELIST *table[],
+ int i1, int j1,
+ int k1, int i2,
+ int j2, int k2,
+ int vid);
+int getedge (EDGELIST *table[],
+ int i1, int j1, int k1,
+ int i2, int j2, int k2);
+void addtovertices (VERTICES *vertices, VERTEX v);
+void vnormal (MB_POINT *point, PROCESS *p, MB_POINT *v);
+void converge (MB_POINT *p1, MB_POINT *p2, float v,
+ float (*function)(float, float, float), MB_POINT *p);
+void polygonize(PROCESS *mbproc);
+float init_meta(Object *ob);
+
+/* **************** METABALL ************************ */
+
+/* void converge (MB_POINT *p1, MB_POINT *p2, float v, float (*function)(void), MB_POINT *p); */
+
+void calc_mballco(MetaElem *ml, float *vec)
+{
+ if(ml->mat) {
+ Mat4MulVecfl(ml->mat, vec);
+ }
+}
+
+
+float thresh= 0.6f;
+int totelem=0;
+MetaElem **mainb;
+
+float densfunc(MetaElem *ball, float x, float y, float z)
+{
+ float dist2 = 0.0, dx, dy, dz;
+ float vec[3];
+
+ if(ball->imat) {
+ vec[0]= x;
+ vec[1]= y;
+ vec[2]= z;
+ Mat4MulVecfl(ball->imat, vec);
+ dx= ball->x - vec[0];
+ dy= ball->y - vec[1];
+ dz= ball->z - vec[2];
+ }
+ else {
+ dx= ball->x - x;
+ dy= ball->y - y;
+ dz= ball->z - z;
+ }
+
+ if(ball->type==MB_BALL) {
+ dist2= (dx*dx + dy*dy + dz*dz);
+ }
+ else if(ball->type & MB_TUBEZ) {
+ if(ball->type==MB_TUBEZ) {
+ if( dz > ball->len) dz-= ball->len;
+ else if(dz< -ball->len) dz+= ball->len;
+ else dz= 0.0;
+ }
+ else if(ball->type==MB_TUBEY) {
+ if( dy > ball->len) dy-= ball->len;
+ else if(dy< -ball->len) dy+= ball->len;
+ else dy= 0.0;
+ }
+ else {
+ if( dx > ball->len) dx-= ball->len;
+ else if(dx< -ball->len) dx+= ball->len;
+ else dx= 0.0;
+ }
+ dist2= (dx*dx + dy*dy + dz*dz);
+ }
+ /* else if(ball->type==MB_CIRCLE) { */
+ /* dist2= 0.5-dz; */
+ /* } */
+
+ if(ball->flag & MB_NEGATIVE) {
+
+ dist2= 1.0f-(dist2/ball->rad2);
+ if(dist2 < 0.0) return 0.5f;
+
+ return 0.5f-ball->s*dist2*dist2*dist2;
+
+ }
+ else {
+ dist2= 1.0f-(dist2/ball->rad2);
+ if(dist2 < 0.0) return -0.5f;
+
+ return ball->s*dist2*dist2*dist2 -0.5f;
+
+ /* return ball->s*sin( dist2); */
+
+ }
+
+}
+
+
+float metaball(float x, float y, float z)
+/* float x, y, z; */
+{
+ float dens=0;
+ int a;
+
+ for(a=0; a<totelem; a++) {
+ dens+= densfunc( mainb[a], x, y, z);
+ }
+
+ return thresh - dens;
+}
+
+/* ******************************************** */
+
+int *indices=0;
+int totindex, curindex;
+
+
+void accum_mballfaces(int i1, int i2, int i3, int i4)
+{
+ int *newi, *cur;
+ /* static int i=0; I would like to delete altogether, but I don't dare to, yet */
+
+ if(totindex==curindex) {
+ totindex+= 256;
+ newi= MEM_mallocN(4*sizeof(int)*totindex, "vertindex");
+
+ if(indices) {
+ memcpy(newi, indices, 4*sizeof(int)*(totindex-256));
+ MEM_freeN(indices);
+ }
+ indices= newi;
+ }
+
+ cur= indices+4*curindex;
+
+ /* voorkomen dat nulcodes voorkomen */
+ if(i3==0) {
+ if(i4) {
+ i3= i4;
+ i4= i1;
+ i1= i2;
+ i2= 0;
+ }
+ else {
+ i3= i2;
+ i2= i1;
+ i1= 0;
+ }
+ }
+
+ cur[0]= i1;
+ cur[1]= i2;
+ cur[2]= i3;
+ cur[3]= i4;
+
+ curindex++;
+
+}
+
+/* ******************* MEMORY MANAGEMENT *********************** */
+
+struct pgn_elements {
+ struct pgn_elements *next, *prev;
+ char *data;
+
+};
+
+void *new_pgn_element(int size)
+{
+ /* gedurende het polygonizeren worden duizenden elementen aangemaakt en
+ * nooit (tussendoor) vrijgegeven. Alleen op eind is vrijgeven nodig.
+ */
+ int blocksize= 16384;
+ static int offs= 0; /* het huidige vrije adres */
+ static struct pgn_elements *cur= 0;
+ static ListBase lb= {0, 0};
+ void *adr;
+
+ if(size>10000 || size==0) {
+ printf("incorrect use of new_pgn_element\n");
+ /* exit(0); */
+ }
+ else if(size== -1) {
+ cur= lb.first;
+ while(cur) {
+ MEM_freeN(cur->data);
+ cur= cur->next;
+ }
+ BLI_freelistN(&lb);
+
+ return NULL;
+ }
+
+ size= 4*( (size+3)/4 );
+
+ if(cur) {
+ if(size+offs < blocksize) {
+ adr= (void *) (cur->data+offs);
+ offs+= size;
+ return adr;
+ }
+ }
+
+ cur= MEM_callocN( sizeof(struct pgn_elements), "newpgn");
+ cur->data= MEM_callocN(blocksize, "newpgn");
+ BLI_addtail(&lb, cur);
+
+ offs= size;
+ return cur->data;
+}
+
+void freepolygonize(PROCESS *p)
+{
+ MEM_freeN(p->corners);
+ MEM_freeN(p->edges);
+ MEM_freeN(p->centers);
+
+ new_pgn_element(-1);
+
+ if(p->vertices.ptr) MEM_freeN(p->vertices.ptr);
+}
+
+/**** Cubical Polygonization (optional) ****/
+
+
+#define LB 0 /* left bottom edge */
+#define LT 1 /* left top edge */
+#define LN 2 /* left near edge */
+#define LF 3 /* left far edge */
+#define RB 4 /* right bottom edge */
+#define RT 5 /* right top edge */
+#define RN 6 /* right near edge */
+#define RF 7 /* right far edge */
+#define BN 8 /* bottom near edge */
+#define BF 9 /* bottom far edge */
+#define TN 10 /* top near edge */
+#define TF 11 /* top far edge */
+
+static INTLISTS *cubetable[256];
+
+/* edge: LB, LT, LN, LF, RB, RT, RN, RF, BN, BF, TN, TF */
+static int corner1[12] = {
+ LBN,LTN,LBN,LBF,RBN,RTN,RBN,RBF,LBN,LBF,LTN,LTF};
+static int corner2[12] = {
+ LBF,LTF,LTN,LTF,RBF,RTF,RTN,RTF,RBN,RBF,RTN,RTF};
+static int leftface[12] = {
+ B, L, L, F, R, T, N, R, N, B, T, F};
+/* face on left when going corner1 to corner2 */
+static int rightface[12] = {
+ L, T, N, L, B, R, R, F, B, F, N, T};
+/* face on right when going corner1 to corner2 */
+
+
+/* docube: triangulate the cube directly, without decomposition */
+
+void docube(CUBE *cube, PROCESS *p)
+{
+ INTLISTS *polys;
+ CORNER *c1, *c2;
+ int i, index = 0, count, indexar[8];
+
+ for (i = 0; i < 8; i++) if (cube->corners[i]->value > 0.0) index += (1<<i);
+
+ for (polys = cubetable[index]; polys; polys = polys->next) {
+ INTLIST *edges;
+
+ count = 0;
+
+ for (edges = polys->list; edges; edges = edges->next) {
+ c1 = cube->corners[corner1[edges->i]];
+ c2 = cube->corners[corner2[edges->i]];
+
+ indexar[count] = vertid(c1, c2, p);
+ count++;
+ }
+ if(count>2) {
+ switch(count) {
+ case 3:
+ accum_mballfaces(indexar[2], indexar[1], indexar[0], 0);
+ break;
+ case 4:
+ if(indexar[0]==0) accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]);
+ else accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]);
+ break;
+ case 5:
+ if(indexar[0]==0) accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]);
+ else accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]);
+
+ accum_mballfaces(indexar[4], indexar[3], indexar[0], 0);
+ break;
+ case 6:
+ if(indexar[0]==0) {
+ accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]);
+ accum_mballfaces(indexar[0], indexar[5], indexar[4], indexar[3]);
+ }
+ else {
+ accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]);
+ accum_mballfaces(indexar[5], indexar[4], indexar[3], indexar[0]);
+ }
+ break;
+ case 7:
+ if(indexar[0]==0) {
+ accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]);
+ accum_mballfaces(indexar[0], indexar[5], indexar[4], indexar[3]);
+ }
+ else {
+ accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]);
+ accum_mballfaces(indexar[5], indexar[4], indexar[3], indexar[0]);
+ }
+
+ accum_mballfaces(indexar[6], indexar[5], indexar[0], 0);
+
+ break;
+ }
+ }
+ }
+}
+
+
+/* testface: given cube at lattice (i, j, k), and four corners of face,
+ * if surface crosses face, compute other four corners of adjacent cube
+ * and add new cube to cube stack */
+
+void testface(int i, int j, int k, CUBE* old, int bit, int c1, int c2, int c3, int c4, PROCESS *p)
+/* CUBE *old; */
+/* PROCESS *p; */
+/* int i, j, k, bit, c1, c2, c3, c4; */
+{
+ CUBE newc;
+ CUBES *oldcubes = p->cubes;
+ CORNER *corn1, *corn2, *corn3, *corn4;
+ int n, pos;
+
+ corn1= old->corners[c1];
+ corn2= old->corners[c2];
+ corn3= old->corners[c3];
+ corn4= old->corners[c4];
+
+ pos = corn1->value > 0.0 ? 1 : 0;
+
+ /* test if no surface crossing */
+ if( (corn2->value > 0) == pos && (corn3->value > 0) == pos && (corn4->value > 0) == pos) return;
+ /* test if cube out of bounds */
+ if ( abs(i) > p->bounds || abs(j) > p->bounds || abs(k) > p->bounds) return;
+ /* test if already visited (always as last) */
+ if (setcenter(p->centers, i, j, k)) return;
+
+
+ /* create new cube and add cube to top of stack: */
+ p->cubes = (CUBES *) new_pgn_element(sizeof(CUBES));
+ p->cubes->next = oldcubes;
+
+ newc.i = i;
+ newc.j = j;
+ newc.k = k;
+ for (n = 0; n < 8; n++) newc.corners[n] = NULL;
+
+ newc.corners[FLIP(c1, bit)] = corn1;
+ newc.corners[FLIP(c2, bit)] = corn2;
+ newc.corners[FLIP(c3, bit)] = corn3;
+ newc.corners[FLIP(c4, bit)] = corn4;
+
+ if(newc.corners[0]==0) newc.corners[0] = setcorner(p, i, j, k);
+ if(newc.corners[1]==0) newc.corners[1] = setcorner(p, i, j, k+1);
+ if(newc.corners[2]==0) newc.corners[2] = setcorner(p, i, j+1, k);
+ if(newc.corners[3]==0) newc.corners[3] = setcorner(p, i, j+1, k+1);
+ if(newc.corners[4]==0) newc.corners[4] = setcorner(p, i+1, j, k);
+ if(newc.corners[5]==0) newc.corners[5] = setcorner(p, i+1, j, k+1);
+ if(newc.corners[6]==0) newc.corners[6] = setcorner(p, i+1, j+1, k);
+ if(newc.corners[7]==0) newc.corners[7] = setcorner(p, i+1, j+1, k+1);
+
+ p->cubes->cube= newc;
+}
+
+/* setcorner: return corner with the given lattice location
+ set (and cache) its function value */
+
+CORNER *setcorner (PROCESS* p, int i, int j, int k)
+/* int i, j, k; */
+/* PROCESS *p; */
+{
+ /* for speed, do corner value caching here */
+ CORNER *c;
+ int index;
+
+ /* bestaat corner al? */
+ index = HASH(i, j, k);
+ c = p->corners[index];
+
+ for (; c != NULL; c = c->next) {
+ if (c->i == i && c->j == j && c->k == k) {
+ return c;
+ }
+ }
+
+ c = (CORNER *) new_pgn_element(sizeof(CORNER));
+
+ c->i = i;
+ c->x = p->start.x+((float)i-0.5f)*p->size;
+ c->j = j;
+ c->y = p->start.y+((float)j-0.5f)*p->size;
+ c->k = k;
+ c->z = p->start.z+((float)k-0.5f)*p->size;
+ c->value = p->function(c->x, c->y, c->z);
+
+ c->next = p->corners[index];
+ p->corners[index] = c;
+
+ return c;
+}
+
+
+/* nextcwedge: return next clockwise edge from given edge around given face */
+
+int nextcwedge (int edge, int face)
+{
+ switch (edge) {
+ case LB:
+ return (face == L)? LF : BN;
+ case LT:
+ return (face == L)? LN : TF;
+ case LN:
+ return (face == L)? LB : TN;
+ case LF:
+ return (face == L)? LT : BF;
+ case RB:
+ return (face == R)? RN : BF;
+ case RT:
+ return (face == R)? RF : TN;
+ case RN:
+ return (face == R)? RT : BN;
+ case RF:
+ return (face == R)? RB : TF;
+ case BN:
+ return (face == B)? RB : LN;
+ case BF:
+ return (face == B)? LB : RF;
+ case TN:
+ return (face == T)? LT : RN;
+ case TF:
+ return (face == T)? RT : LF;
+ }
+ return 0;
+}
+
+
+/* otherface: return face adjoining edge that is not the given face */
+
+int otherface (int edge, int face)
+/* int edge, face; */
+{
+ int other = leftface[edge];
+ return face == other? rightface[edge] : other;
+}
+
+
+/* makecubetable: create the 256 entry table for cubical polygonization */
+
+void makecubetable (void)
+{
+ static int isdone= 0;
+ int i, e, c, done[12], pos[8];
+
+ if(isdone) return;
+ isdone= 1;
+
+ for (i = 0; i < 256; i++) {
+ for (e = 0; e < 12; e++) done[e] = 0;
+ for (c = 0; c < 8; c++) pos[c] = MB_BIT(i, c);
+ for (e = 0; e < 12; e++)
+ if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) {
+ INTLIST *ints = 0;
+ INTLISTS *lists = (INTLISTS *) MEM_callocN(sizeof(INTLISTS), "mball_intlist");
+ int start = e, edge = e;
+
+ /* get face that is to right of edge from pos to neg corner: */
+ int face = pos[corner1[e]]? rightface[e] : leftface[e];
+
+ while (1) {
+ edge = nextcwedge(edge, face);
+ done[edge] = 1;
+ if (pos[corner1[edge]] != pos[corner2[edge]]) {
+ INTLIST *tmp = ints;
+
+ ints = (INTLIST *) MEM_callocN(sizeof(INTLIST), "mball_intlist");
+ ints->i = edge;
+ ints->next = tmp; /* add edge to head of list */
+
+ if (edge == start) break;
+ face = otherface(edge, face);
+ }
+ }
+ lists->list = ints; /* add ints to head of table entry */
+ lists->next = cubetable[i];
+ cubetable[i] = lists;
+ }
+ }
+}
+
+void BKE_freecubetable(void)
+{
+ int i;
+ INTLISTS *lists, *nlists;
+ INTLIST *ints, *nints;
+
+ for (i = 0; i < 256; i++) {
+ lists= cubetable[i];
+ while(lists) {
+ nlists= lists->next;
+
+ ints= lists->list;
+ while(ints) {
+ nints= ints->next;
+ MEM_freeN(ints);
+ ints= nints;
+ }
+
+ MEM_freeN(lists);
+ lists= nlists;
+ }
+ cubetable[i]= 0;
+ }
+}
+
+/**** Storage ****/
+
+/* setcenter: set (i,j,k) entry of table[]
+ * return 1 if already set; otherwise, set and return 0 */
+
+int setcenter(CENTERLIST *table[], int i, int j, int k)
+/* CENTERLIST *table[]; */
+/* int i, j, k; */
+{
+ int index;
+ CENTERLIST *newc, *l, *q;
+
+ index= HASH(i, j, k);
+ q= table[index];
+
+ for (l = q; l != NULL; l = l->next) {
+ if (l->i == i && l->j == j && l->k == k) return 1;
+ }
+
+ newc = (CENTERLIST *) new_pgn_element(sizeof(CENTERLIST));
+ newc->i = i;
+ newc->j = j;
+ newc->k = k;
+ newc->next = q;
+ table[index] = newc;
+
+ return 0;
+}
+
+
+/* setedge: set vertex id for edge */
+
+void setedge (EDGELIST *table[],
+ int i1, int j1,
+ int k1, int i2,
+ int j2, int k2,
+ int vid)
+/* EDGELIST *table[]; */
+/* int i1, j1, k1, i2, j2, k2, vid; */
+{
+ unsigned int index;
+ EDGELIST *newe;
+
+ if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) {
+ int t=i1;
+ i1=i2;
+ i2=t;
+ t=j1;
+ j1=j2;
+ j2=t;
+ t=k1;
+ k1=k2;
+ k2=t;
+ }
+ index = HASH(i1, j1, k1) + HASH(i2, j2, k2);
+ newe = (EDGELIST *) new_pgn_element(sizeof(EDGELIST));
+ newe->i1 = i1;
+ newe->j1 = j1;
+ newe->k1 = k1;
+ newe->i2 = i2;
+ newe->j2 = j2;
+ newe->k2 = k2;
+ newe->vid = vid;
+ newe->next = table[index];
+ table[index] = newe;
+}
+
+
+/* getedge: return vertex id for edge; return -1 if not set */
+
+int getedge (EDGELIST *table[],
+ int i1, int j1, int k1,
+ int i2, int j2, int k2)
+/* EDGELIST *table[]; */
+/* int i1, j1, k1, i2, j2, k2; */
+{
+ EDGELIST *q;
+
+ if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) {
+ int t=i1;
+ i1=i2;
+ i2=t;
+ t=j1;
+ j1=j2;
+ j2=t;
+ t=k1;
+ k1=k2;
+ k2=t;
+ }
+ q = table[HASH(i1, j1, k1)+HASH(i2, j2, k2)];
+ for (; q != NULL; q = q->next)
+ if (q->i1 == i1 && q->j1 == j1 && q->k1 == k1 &&
+ q->i2 == i2 && q->j2 == j2 && q->k2 == k2)
+ return q->vid;
+ return -1;
+}
+
+
+/**** Vertices ****/
+
+#undef R
+
+
+
+/* vertid: return index for vertex on edge:
+ * c1->value and c2->value are presumed of different sign
+ * return saved index if any; else compute vertex and save */
+
+/* addtovertices: add v to sequence of vertices */
+
+void addtovertices (VERTICES *vertices, VERTEX v)
+/* VERTICES *vertices; */
+/* VERTEX v; */
+{
+ if (vertices->count == vertices->max) {
+ int i;
+ VERTEX *newv;
+ vertices->max = vertices->count == 0 ? 10 : 2*vertices->count;
+ newv = (VERTEX *) MEM_callocN(vertices->max * sizeof(VERTEX), "addtovertices");
+
+ for (i = 0; i < vertices->count; i++) newv[i] = vertices->ptr[i];
+
+ if (vertices->ptr != NULL) MEM_freeN(vertices->ptr);
+ vertices->ptr = newv;
+ }
+ vertices->ptr[vertices->count++] = v;
+}
+
+/* vnormal: compute unit length surface normal at point */
+
+void vnormal (MB_POINT *point, PROCESS *p, MB_POINT *v)
+/* MB_POINT *point, *v; */
+/* PROCESS *p; */
+{
+ float delta= 0.2f*p->delta;
+ float f = p->function(point->x, point->y, point->z);
+
+ v->x = p->function(point->x+delta, point->y, point->z)-f;
+ v->y = p->function(point->x, point->y+delta, point->z)-f;
+ v->z = p->function(point->x, point->y, point->z+delta)-f;
+ f = (float)sqrt(v->x*v->x + v->y*v->y + v->z*v->z);
+
+ if (f != 0.0) {
+ v->x /= f;
+ v->y /= f;
+ v->z /= f;
+ }
+
+ if(FALSE) {
+ /* if(R.flag & R_RENDERING) { */
+ MB_POINT temp;
+
+ delta*= 2.0;
+
+ f = p->function(point->x, point->y, point->z);
+
+ temp.x = p->function(point->x+delta, point->y, point->z)-f;
+ temp.y = p->function(point->x, point->y+delta, point->z)-f;
+ temp.z = p->function(point->x, point->y, point->z+delta)-f;
+ f = (float)sqrt(temp.x*temp.x + temp.y*temp.y + temp.z*temp.z);
+
+ if (f != 0.0) {
+ temp.x /= f;
+ temp.y /= f;
+ temp.z /= f;
+
+ v->x+= temp.x;
+ v->y+= temp.y;
+ v->z+= temp.z;
+
+ f = (float)sqrt(v->x*v->x + v->y*v->y + v->z*v->z);
+
+ if (f != 0.0) {
+ v->x /= f;
+ v->y /= f;
+ v->z /= f;
+ }
+ }
+ }
+
+}
+
+
+int vertid (CORNER *c1, CORNER *c2, PROCESS *p)
+/* CORNER *c1, *c2; */
+/* PROCESS *p; */
+{
+ VERTEX v;
+ MB_POINT a, b;
+ int vid = getedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k);
+
+ if (vid != -1) return vid; /* previously computed */
+ a.x = c1->x;
+ a.y = c1->y;
+ a.z = c1->z;
+ b.x = c2->x;
+ b.y = c2->y;
+ b.z = c2->z;
+
+ converge(&a, &b, c1->value, p->function, &v.position); /* position */
+ vnormal(&v.position, p, &v.normal);
+
+ addtovertices(&p->vertices, v); /* save vertex */
+ vid = p->vertices.count-1;
+ setedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid);
+
+ return vid;
+}
+
+
+
+
+/* converge: from two points of differing sign, converge to zero crossing */
+/* watch it: p1 and p2 are used to calculate */
+
+void converge (MB_POINT *p1, MB_POINT *p2, float v,
+ float (*function)(float, float, float), MB_POINT *p)
+{
+ int i = 0;
+ MB_POINT *pos, *neg;
+
+ if (v < 0) {
+ pos= p2;
+ neg= p1;
+ }
+ else {
+ pos= p1;
+ neg= p2;
+ }
+ while (1) {
+ p->x = 0.5f*(pos->x + neg->x);
+ p->y = 0.5f*(pos->y + neg->y);
+ p->z = 0.5f*(pos->z + neg->z);
+
+ if (i++ == RES) return;
+
+ if ((function(p->x, p->y, p->z)) > 0.0) {
+ pos->x = p->x;
+ pos->y = p->y;
+ pos->z = p->z;
+ }
+ else {
+ neg->x = p->x;
+ neg->y = p->y;
+ neg->z = p->z;
+ }
+ }
+}
+
+/* ************************************** */
+
+
+void polygonize(PROCESS *mbproc)
+{
+ MB_POINT in, out;
+ CUBE c;
+ CUBES *ncube;
+/* CORNER *setcorner(); */
+ int a, n, i, j, k;
+
+ mbproc->vertices.count = mbproc->vertices.max = 0;
+ mbproc->vertices.ptr = NULL;
+
+ /* allocate hash tables and build cube polygon table: */
+ mbproc->centers = MEM_callocN(HASHSIZE * sizeof(CENTERLIST *), "mbproc->centers");
+ mbproc->corners = MEM_callocN(HASHSIZE * sizeof(CORNER *), "mbproc->corners");
+ mbproc->edges = MEM_callocN(2*HASHSIZE * sizeof(EDGELIST *), "mbproc->edges");
+ makecubetable();
+
+ /* find first point on balls */
+ for(a=0; a<totelem; a++) {
+
+ in.x= mainb[a]->x;
+ in.y= mainb[a]->y;
+ in.z= mainb[a]->z;
+ calc_mballco(mainb[a], (float *)&in);
+
+ /* added factor 2.0 to be sure it always finds the ball... still unsure why! */
+
+ out.x= in.x + 2.0f*mainb[a]->rad;
+ out.y= in.y + 2.0f*mainb[a]->rad;
+ out.z= in.z + 2.0f*mainb[a]->rad;
+ calc_mballco(mainb[a], (float *)&out);
+
+ converge(&in, &out, -1.0, mbproc->function, &mbproc->start);
+
+ /* NEW1: zorg voor correcte uitgangspositie */
+ i= (int)floor(mbproc->start.x/mbproc->size );
+ j= (int)floor(mbproc->start.y/mbproc->size );
+ k= (int)floor(mbproc->start.z/mbproc->size );
+
+ mbproc->start.x= mbproc->start.y= mbproc->start.z= 0.0;
+
+/* dit gaat niet altijd goed: soms wordt een bal niet gevonden. waarom? */
+
+ /* test if cube has been found before */
+ if( setcenter(mbproc->centers, i, j, k)==0 ) {
+
+ /* push cube on stack: */
+ ncube= (CUBES *) new_pgn_element(sizeof(CUBES));
+ ncube->next= mbproc->cubes;
+ mbproc->cubes= ncube;
+
+ ncube->cube.i= i;
+ ncube->cube.j= j;
+ ncube->cube.k= k;
+
+ /* set corners of initial cube: */
+ for (n = 0; n < 8; n++)
+ ncube->cube.corners[n] = setcorner(mbproc, i+MB_BIT(n,2), j+MB_BIT(n,1), k+MB_BIT(n,0));
+ }
+
+ /* we do a triple test and add a cube if necessary */
+ i++;
+
+ /* test if cube has been found before */
+ if( setcenter(mbproc->centers, i, j, k)==0 ) {
+
+ /* push cube on stack: */
+ ncube= (CUBES *) new_pgn_element(sizeof(CUBES));
+ ncube->next= mbproc->cubes;
+ mbproc->cubes= ncube;
+
+ ncube->cube.i= i;
+ ncube->cube.j= j;
+ ncube->cube.k= k;
+
+ /* set corners of initial cube: */
+ for (n = 0; n < 8; n++)
+ ncube->cube.corners[n] = setcorner(mbproc, i+MB_BIT(n,2), j+MB_BIT(n,1), k+MB_BIT(n,0));
+ }
+
+ i--;
+ j++;
+
+ /* test if cube has been found before */
+ if( setcenter(mbproc->centers, i, j, k)==0 ) {
+
+ /* push cube on stack: */
+ ncube= (CUBES *) new_pgn_element(sizeof(CUBES));
+ ncube->next= mbproc->cubes;
+ mbproc->cubes= ncube;
+
+ ncube->cube.i= i;
+ ncube->cube.j= j;
+ ncube->cube.k= k;
+
+ /* set corners of initial cube: */
+ for (n = 0; n < 8; n++)
+ ncube->cube.corners[n] = setcorner(mbproc, i+MB_BIT(n,2), j+MB_BIT(n,1), k+MB_BIT(n,0));
+ }
+
+ j--;
+ k++;
+
+ /* test if cube has been found before */
+ if( setcenter(mbproc->centers, i, j, k)==0 ) {
+
+ /* push cube on stack: */
+ ncube= (CUBES *) new_pgn_element(sizeof(CUBES));
+ ncube->next= mbproc->cubes;
+ mbproc->cubes= ncube;
+
+ ncube->cube.i= i;
+ ncube->cube.j= j;
+ ncube->cube.k= k;
+
+ /* set corners of initial cube: */
+ for (n = 0; n < 8; n++)
+ ncube->cube.corners[n] = setcorner(mbproc, i+MB_BIT(n,2), j+MB_BIT(n,1), k+MB_BIT(n,0));
+ }
+
+ i++;
+ j++;
+
+ /* test if cube has been found before */
+ if( setcenter(mbproc->centers, i, j, k)==0 ) {
+
+ /* push cube on stack: */
+ ncube= (CUBES *) new_pgn_element(sizeof(CUBES));
+ ncube->next= mbproc->cubes;
+ mbproc->cubes= ncube;
+
+ ncube->cube.i= i;
+ ncube->cube.j= j;
+ ncube->cube.k= k;
+
+ /* set corners of initial cube: */
+ for (n = 0; n < 8; n++)
+ ncube->cube.corners[n] = setcorner(mbproc, i+MB_BIT(n,2), j+MB_BIT(n,1), k+MB_BIT(n,0));
+ }
+ }
+
+ while (mbproc->cubes != NULL) { /* process active cubes till none left */
+ c = mbproc->cubes->cube;
+
+ /* polygonize the cube directly: */
+ docube(&c, mbproc);
+
+ /* pop current cube from stack */
+ mbproc->cubes = mbproc->cubes->next;
+
+ /* test six face directions, maybe add to stack: */
+ testface(c.i-1, c.j, c.k, &c, 2, LBN, LBF, LTN, LTF, mbproc);
+ testface(c.i+1, c.j, c.k, &c, 2, RBN, RBF, RTN, RTF, mbproc);
+ testface(c.i, c.j-1, c.k, &c, 1, LBN, LBF, RBN, RBF, mbproc);
+ testface(c.i, c.j+1, c.k, &c, 1, LTN, LTF, RTN, RTF, mbproc);
+ testface(c.i, c.j, c.k-1, &c, 0, LBN, LTN, RBN, RTN, mbproc);
+ testface(c.i, c.j, c.k+1, &c, 0, LBF, LTF, RBF, RTF, mbproc);
+ }
+
+}
+
+float init_meta(Object *ob) /* return totsize */
+{
+ Base *base;
+ Object *bob;
+ MetaBall *mb;
+ MetaElem *ml;
+ float size, totsize, (*mat)[4] = NULL, (*imat)[4] = NULL, obinv[4][4], vec[3];
+ int a, obnr;
+ char obname[32];
+
+ Mat4Invert(obinv, ob->obmat);
+ totelem= 0;
+
+ splitIDname(ob->id.name+2, obname, &obnr);
+
+ /* hoofdarray maken */
+
+ next_object(0, 0, 0);
+ while(next_object(1, &base, &bob)) {
+
+ if(bob->type==OB_MBALL) {
+ ml= 0;
+ if(bob==ob) {
+ mat= imat= 0;
+ mb= ob->data;
+
+ if(ob==G.obedit) ml= editelems.first;
+ else if(G.obedit && G.obedit->type==OB_MBALL && G.obedit->data==mb) ml= editelems.first;
+ else ml= mb->elems.first;
+ }
+ else {
+ char name[32];
+ int nr;
+
+ splitIDname(bob->id.name+2, name, &nr);
+ if( strcmp(obname, name)==0 ) {
+ mb= bob->data;
+
+ if(G.obedit && G.obedit->type==OB_MBALL && G.obedit->data==mb)
+ ml= editelems.first;
+ else ml= mb->elems.first;
+
+ /* mat is de matrix om van deze mball in de basis-mbal te komen */
+ mat= new_pgn_element(4*4*sizeof(float));
+ Mat4MulMat4(mat, bob->obmat, obinv);
+
+ imat= new_pgn_element(4*4*sizeof(float));
+ Mat4Invert(imat, mat);
+
+ }
+ }
+ while(ml && totelem<MB_MAXELEM) {
+ a= totelem;
+
+ /* kopie maken i.v.m. duplicates */
+ mainb[a]= new_pgn_element(sizeof(MetaElem));
+ *(mainb[a])= *ml;
+
+ /* if(mainb[a]->flag & MB_NEGATIVE) mainb[a]->s= 1.0-mainb[a]->s; */
+ mainb[a]->rad2= mainb[a]->rad*mainb[a]->rad;
+
+ mainb[a]->mat= (float*) mat;
+ mainb[a]->imat= (float*) imat;
+
+ ml= ml->next;
+ totelem++;
+
+ }
+ }
+ }
+
+ /* totsize (= 'manhattan' straal) berekenen */
+ totsize= 0.0;
+ for(a=0; a<totelem; a++) {
+
+ vec[0]= mainb[a]->x + mainb[a]->rad;
+ vec[1]= mainb[a]->y + mainb[a]->rad;
+ vec[2]= mainb[a]->z + mainb[a]->rad;
+
+ if(mainb[a]->type==MB_TUBEX) vec[0]+= mainb[a]->len;
+ if(mainb[a]->type==MB_TUBEY) vec[1]+= mainb[a]->len;
+ if(mainb[a]->type==MB_TUBEZ) vec[2]+= mainb[a]->len;
+
+ calc_mballco(mainb[a], vec);
+
+ size= (float)fabs( vec[0] );
+ if( size > totsize ) totsize= size;
+ size= (float)fabs( vec[1] );
+ if( size > totsize ) totsize= size;
+ size= (float)fabs( vec[2] );
+ if( size > totsize ) totsize= size;
+
+ vec[0]= mainb[a]->x - mainb[a]->rad;
+ vec[1]= mainb[a]->y - mainb[a]->rad;
+ vec[2]= mainb[a]->z - mainb[a]->rad;
+
+ calc_mballco(mainb[a], vec);
+
+ size= (float)fabs( vec[0] );
+ if( size > totsize ) totsize= size;
+ size= (float)fabs( vec[1] );
+ if( size > totsize ) totsize= size;
+ size= (float)fabs( vec[2] );
+ if( size > totsize ) totsize= size;
+ }
+
+ for(a=0; a<totelem; a++) {
+ thresh+= densfunc( mainb[a], 2.0f*totsize, 2.0f*totsize, 2.0f*totsize);
+ }
+
+ return totsize;
+}
+
+void metaball_polygonize(Object *ob)
+{
+ PROCESS mbproc;
+ MetaBall *mb;
+ DispList *dl;
+ int a, nr_cubes;
+ float *ve, *no, totsize, width;
+
+ mb= ob->data;
+
+ freedisplist(&ob->disp);
+ curindex= totindex= 0;
+ indices= 0;
+ thresh= mb->thresh;
+
+ if(G.moving && mb->flag==MB_UPDATE_FAST) return;
+
+ mainb= MEM_mallocN(sizeof(void *)*MB_MAXELEM, "mainb");
+
+ totsize= init_meta(ob);
+ if(totelem==0) {
+ MEM_freeN(mainb);
+ return;
+ }
+
+ /* width is afmeting per polygoniseerkubus */
+ if(R.flag & R_RENDERING) width= mb->rendersize;
+ else {
+ width= mb->wiresize;
+ if(G.moving && mb->flag==MB_UPDATE_HALFRES) width*= 2;
+ }
+ /* nr_cubes is voor de veiligheid, minmaal de totsize */
+ nr_cubes= (int)(0.5+totsize/width);
+
+ /* init process */
+ mbproc.function = metaball;
+ mbproc.size = width;
+ mbproc.bounds = nr_cubes;
+ mbproc.cubes= 0;
+ mbproc.delta = width/(float)(RES*RES);
+
+ polygonize(&mbproc);
+
+ MEM_freeN(mainb);
+
+ if(curindex) {
+
+ dl= MEM_callocN(sizeof(DispList), "mbaldisp");
+ BLI_addtail(&ob->disp, dl);
+ dl->type= DL_INDEX4;
+ dl->nr= mbproc.vertices.count;
+ dl->parts= curindex;
+
+ dl->index= indices;
+ indices= 0;
+
+ a= mbproc.vertices.count;
+ dl->verts= ve= MEM_mallocN(sizeof(float)*3*a, "mballverts");
+ dl->nors= no= MEM_mallocN(sizeof(float)*3*a, "mballnors");
+
+ for(a=0; a<mbproc.vertices.count; a++, no+=3, ve+=3) {
+ ve[0]= mbproc.vertices.ptr[a].position.x;
+ ve[1]= mbproc.vertices.ptr[a].position.y;
+ ve[2]= mbproc.vertices.ptr[a].position.z;
+
+ no[0]= mbproc.vertices.ptr[a].normal.x;
+ no[1]= mbproc.vertices.ptr[a].normal.y;
+ no[2]= mbproc.vertices.ptr[a].normal.z;
+ }
+ }
+
+ freepolygonize(&mbproc);
+
+}
+
+
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
new file mode 100644
index 00000000000..720d02ee7bb
--- /dev/null
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -0,0 +1,1120 @@
+
+/* mesh.c MIXED MODEL
+ *
+ * jan/maart 95
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_curve_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_image_types.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BKE_main.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_subsurf.h"
+#include "BKE_displist.h"
+#include "BKE_library.h"
+#include "BKE_material.h"
+#include "BKE_key.h"
+/* these 2 are only used by conversion functions */
+#include "BKE_curve.h"
+/* -- */
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_bad_level_calls.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_arithb.h"
+
+
+
+int update_realtime_texture(TFace *tface, double time)
+{
+ Image *ima;
+ int inc = 0;
+ float diff;
+ int newframe;
+
+ ima = tface->tpage;
+
+ if (!ima)
+ return 0;
+
+ if (ima->lastupdate<0)
+ ima->lastupdate = 0;
+
+ if (ima->lastupdate>time)
+ ima->lastupdate=(float)time;
+
+ if(ima->tpageflag & IMA_TWINANIM) {
+ if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1;
+
+ /* check: zit de bindcode niet het array? Vrijgeven. (nog doen) */
+
+ diff = (float)(time-ima->lastupdate);
+
+ inc = (int)(diff*(float)ima->animspeed);
+
+ ima->lastupdate+=((float)inc/(float)ima->animspeed);
+
+ newframe = ima->lastframe+inc;
+
+ if (newframe > (int)ima->twend)
+ newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta);
+
+ ima->lastframe = newframe;
+ }
+ return inc;
+}
+
+float get_mvert_weight (Object *ob, int vert, int defgroup)
+{
+ int i;
+ Mesh *me;
+ float result;
+
+ me=ob->data;
+
+ if (!me->dvert)
+ return 0.0F;
+
+ result=0.0F;
+
+ for (i=0; i<me->dvert[vert].totweight; i++){
+ if (me->dvert[vert].dw[i].def_nr==defgroup)
+ result+=me->dvert[vert].dw[i].weight;
+ }
+
+ return result;
+}
+
+void unlink_mesh(Mesh *me)
+{
+ int a;
+
+ if(me==0) return;
+
+ for(a=0; a<me->totcol; a++) {
+ if(me->mat[a]) me->mat[a]->id.us--;
+ me->mat[a]= 0;
+ }
+ if(me->key) me->key->id.us--;
+ me->key= 0;
+
+ if(me->texcomesh) me->texcomesh= 0;
+}
+
+
+/* niet mesh zelf vrijgeven */
+void free_mesh(Mesh *me)
+{
+
+ unlink_mesh(me);
+
+ if(me->mat) MEM_freeN(me->mat);
+ if(me->orco) MEM_freeN(me->orco);
+ if(me->mface) MEM_freeN(me->mface);
+ if(me->tface) MEM_freeN(me->tface);
+ if(me->mvert) MEM_freeN(me->mvert);
+ if(me->dvert) free_dverts(me->dvert, me->totvert);
+ if(me->mcol) MEM_freeN(me->mcol);
+ if(me->msticky) MEM_freeN(me->msticky);
+ if(me->bb) MEM_freeN(me->bb);
+ if(me->disp.first) freedisplist(&me->disp);
+}
+
+void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount)
+{
+ /* Assumes dst is already set up */
+ int i;
+
+ if (!src || !dst)
+ return;
+
+ memcpy (dst, src, copycount * sizeof(MDeformVert));
+
+ for (i=0; i<copycount; i++){
+ if (src[i].dw){
+ dst[i].dw = MEM_callocN (sizeof(MDeformWeight)*src[i].totweight, "copy_deformWeight");
+ memcpy (dst[i].dw, src[i].dw, sizeof (MDeformWeight)*src[i].totweight);
+ }
+ }
+
+}
+void free_dverts(MDeformVert *dvert, int totvert)
+{
+ /* Instead of freeing the verts directly,
+ call this function to delete any special
+ vert data */
+ int i;
+
+ if (!dvert)
+ return;
+
+ /* Free any special data from the verts */
+ for (i=0; i<totvert; i++){
+ if (dvert[i].dw) MEM_freeN (dvert[i].dw);
+ }
+ MEM_freeN (dvert);
+}
+
+Mesh *add_mesh()
+{
+ Mesh *me;
+
+ me= alloc_libblock(&G.main->mesh, ID_ME, "Mesh");
+
+ me->size[0]= me->size[1]= me->size[2]= 1.0;
+ me->smoothresh= 30;
+ me->texflag= AUTOSPACE;
+ me->flag= ME_TWOSIDED;
+ me->subdiv= 1;
+ me->subdivr = 1;
+ me->bb= unit_boundbox();
+
+ return me;
+}
+
+Mesh *copy_mesh(Mesh *me)
+{
+ Mesh *men;
+ int a;
+
+ men= copy_libblock(me);
+
+ men->mat= MEM_dupallocN(me->mat);
+ for(a=0; a<men->totcol; a++) {
+ id_us_plus((ID *)men->mat[a]);
+ }
+ id_us_plus((ID *)men->texcomesh);
+ men->mface= MEM_dupallocN(me->mface);
+
+ men->tface= MEM_dupallocN(me->tface);
+
+ men->dface= 0;
+ men->mvert= MEM_dupallocN(me->mvert);
+ memcpy (men->mvert, me->mvert, sizeof (MVert)*me->totvert);
+ if (me->dvert){
+ men->dvert = MEM_mallocN (sizeof (MDeformVert)*me->totvert, "MDeformVert");
+ copy_dverts(men->dvert, me->dvert, me->totvert);
+ }
+
+ men->mcol= MEM_dupallocN(me->mcol);
+ men->msticky= MEM_dupallocN(me->msticky);
+ men->texcomesh= 0;
+ men->orco= 0;
+ men->bb= MEM_dupallocN(men->bb);
+
+ copy_displist(&men->disp, &me->disp);
+
+ men->key= copy_key(me->key);
+ if(men->key) men->key->from= (ID *)men;
+
+ return men;
+}
+
+void make_local_tface(Mesh *me)
+{
+ TFace *tface;
+ Image *ima;
+ int a;
+
+ if(me->tface==0) return;
+
+ a= me->totface;
+ tface= me->tface;
+ while(a--) {
+
+ /* speciaal geval: ima altijd meteen lokaal */
+ if(tface->tpage) {
+ ima= tface->tpage;
+ if(ima->id.lib) {
+ ima->id.lib= 0;
+ ima->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ima, 0);
+ }
+ }
+ tface++;
+ }
+
+}
+
+void make_local_mesh(Mesh *me)
+{
+ Object *ob;
+ Mesh *men;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(me->id.lib==0) return;
+ if(me->id.us==1) {
+ me->id.lib= 0;
+ me->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)me, 0);
+
+ if(me->tface) make_local_tface(me);
+
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if( me==get_mesh(ob) ) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ me->id.lib= 0;
+ me->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)me, 0);
+
+ if(me->tface) make_local_tface(me);
+
+ }
+ else if(local && lib) {
+ men= copy_mesh(me);
+ men->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if( me==get_mesh(ob) ) {
+ if(ob->id.lib==0) {
+ set_mesh(ob, men);
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+void boundbox_mesh(Mesh *me, float *loc, float *size)
+{
+ MVert *mvert;
+ BoundBox *bb;
+ float min[3], max[3];
+ float mloc[3], msize[3];
+ int a;
+
+ if(me->bb==0) me->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
+ bb= me->bb;
+
+ INIT_MINMAX(min, max);
+
+ if (!loc) loc= mloc;
+ if (!size) size= msize;
+
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ DO_MINMAX(mvert->co, min, max);
+ }
+
+ if(me->totvert) {
+ loc[0]= (min[0]+max[0])/2.0f;
+ loc[1]= (min[1]+max[1])/2.0f;
+ loc[2]= (min[2]+max[2])/2.0f;
+
+ size[0]= (max[0]-min[0])/2.0f;
+ size[1]= (max[1]-min[1])/2.0f;
+ size[2]= (max[2]-min[2])/2.0f;
+ }
+ else {
+ loc[0]= loc[1]= loc[2]= 0.0;
+ size[0]= size[1]= size[2]= 0.0;
+ }
+
+ bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= loc[0]-size[0];
+ bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= loc[0]+size[0];
+
+ bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= loc[1]-size[1];
+ bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= loc[1]+size[1];
+
+ bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= loc[2]-size[2];
+ bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= loc[2]+size[2];
+}
+
+void tex_space_mesh(Mesh *me)
+{
+ KeyBlock *kb;
+ float *fp, loc[3], size[3], min[3], max[3];
+ int a;
+
+ boundbox_mesh(me, loc, size);
+
+ if(me->texflag & AUTOSPACE) {
+ if(me->key) {
+ kb= me->key->refkey;
+ if (kb) {
+
+ INIT_MINMAX(min, max);
+
+ fp= kb->data;
+ for(a=0; a<kb->totelem; a++, fp+=3) {
+ DO_MINMAX(fp, min, max);
+ }
+ if(kb->totelem) {
+ loc[0]= (min[0]+max[0])/2.0f; loc[1]= (min[1]+max[1])/2.0f; loc[2]= (min[2]+max[2])/2.0f;
+ size[0]= (max[0]-min[0])/2.0f; size[1]= (max[1]-min[1])/2.0f; size[2]= (max[2]-min[2])/2.0f;
+ }
+ else {
+ loc[0]= loc[1]= loc[2]= 0.0;
+ size[0]= size[1]= size[2]= 0.0;
+ }
+
+ }
+ }
+
+ VECCOPY(me->loc, loc);
+ VECCOPY(me->size, size);
+ me->rot[0]= me->rot[1]= me->rot[2]= 0.0;
+
+ if(me->size[0]==0.0) me->size[0]= 1.0;
+ else if(me->size[0]>0.0 && me->size[0]<0.00001) me->size[0]= 0.00001;
+ else if(me->size[0]<0.0 && me->size[0]> -0.00001) me->size[0]= -0.00001;
+
+ if(me->size[1]==0.0) me->size[1]= 1.0;
+ else if(me->size[1]>0.0 && me->size[1]<0.00001) me->size[1]= 0.00001;
+ else if(me->size[1]<0.0 && me->size[1]> -0.00001) me->size[1]= -0.00001;
+
+ if(me->size[2]==0.0) me->size[2]= 1.0;
+ else if(me->size[2]>0.0 && me->size[2]<0.00001) me->size[2]= 0.00001;
+ else if(me->size[2]<0.0 && me->size[2]> -0.00001) me->size[2]= -0.00001;
+ }
+
+}
+
+void make_orco_displist_mesh(Object *ob, int subdivlvl)
+{
+ Mesh *me;
+ DispList *dl;
+ DispListMesh *dlm;
+ int i;
+
+ me= ob->data;
+
+ /* if there's a key, set the first one */
+ if(me->key && me->texcomesh==0) {
+ cp_key(0, me->totvert, me->totvert, (char*) me->mvert->co, me->key, me->key->refkey, 0);
+ }
+
+ /* Rebuild the displist */
+ dl= subsurf_mesh_to_displist(me, NULL, (short)subdivlvl);
+
+ /* Restore correct key */
+ do_ob_key(ob);
+
+ /* XXX Assume dl is a DL_MESH (it is),
+ * should be explicit -zr
+ */
+ dlm= dl->mesh;
+
+ me->orco= MEM_mallocN(dlm->totvert*3*sizeof(float), "mesh displist orco");
+
+ for (i=0; i<dlm->totvert; i++) {
+ float *fp= &me->orco[i*3];
+ VECCOPY(fp, dlm->mvert[i].co);
+ }
+
+ for(i=0; i<dlm->totvert; i++) {
+ float *fp= &me->orco[i*3];
+ fp[0]= (fp[0]-me->loc[0])/me->size[0];
+ fp[1]= (fp[1]-me->loc[1])/me->size[1];
+ fp[2]= (fp[2]-me->loc[2])/me->size[2];
+ }
+
+ free_disp_elem(dl);
+}
+
+void make_orco_mesh(Mesh *me)
+{
+ MVert *mvert;
+ KeyBlock *kb;
+ float *orco, *fp;
+ int a, totvert;
+
+ totvert= me->totvert;
+ if(totvert==0) return;
+ orco= me->orco= MEM_mallocN(sizeof(float)*3*totvert, "orco mesh");
+
+ if(me->key && me->texcomesh==0) {
+ kb= me->key->refkey;
+ if (kb) { /***** BUG *****/
+ fp= kb->data;
+
+ for(a=0; a<totvert; a++, orco+=3) {
+ orco[0]= (fp[0]-me->loc[0])/me->size[0];
+ orco[1]= (fp[1]-me->loc[1])/me->size[1];
+ orco[2]= (fp[2]-me->loc[2])/me->size[2];
+
+ /* mvert alleen ophogen als totvert <= kb->totelem */
+ if(a<kb->totelem) fp+=3;
+ }
+ }
+ }
+ else {
+ if(me->texcomesh) {
+ me= me->texcomesh;
+ }
+
+ mvert= me->mvert;
+ for(a=0; a<totvert; a++, orco+=3) {
+ orco[0]= (mvert->co[0]-me->loc[0])/me->size[0];
+ orco[1]= (mvert->co[1]-me->loc[1])/me->size[1];
+ orco[2]= (mvert->co[2]-me->loc[2])/me->size[2];
+
+ /* mvert alleen ophogen als totvert <= me->totvert */
+ if(a<me->totvert) mvert++;
+ }
+ }
+}
+
+/** rotates the vertices of a face in case v[2] or v[3] (vertex index)
+ * is = 0.
+ * Helaas, the MFace structure has no pointer to its
+ * texture face, therefore, texture can not be fixed inside
+ * this function.
+ *
+ * see also blender/src/editmesh.c, fix_faceindices()
+
+ * THIS FUNCTION WILL BE DINOSOURCE. For the moment, another hack
+ is added to fix texture coordinates / vertex colors:
+
+ void test_index_face(MFace *mface, TFace *tface, int nr)
+ */
+
+void test_index_mface(MFace *mface, int nr)
+{
+ int a;
+
+
+ /* first test if the face is legal */
+
+ if(mface->v3 && mface->v3==mface->v4) {
+ mface->v4= 0;
+ nr--;
+ }
+ if(mface->v2 && mface->v2==mface->v3) {
+ mface->v3= mface->v4;
+ mface->v4= 0;
+ nr--;
+ }
+ if(mface->v1==mface->v2) {
+ mface->v2= mface->v3;
+ mface->v3= mface->v4;
+ mface->v4= 0;
+ nr--;
+ }
+
+ /* voorkom dat een nul op de verkeerde plek staat */
+ if(nr==2) {
+ if(mface->v2==0) SWAP(int, mface->v1, mface->v2);
+ }
+ else if(nr==3) {
+ if(mface->v3==0) {
+ SWAP(int, mface->v1, mface->v2);
+ SWAP(int, mface->v2, mface->v3);
+
+ a= mface->edcode;
+ mface->edcode= 0;
+ if(a & ME_V1V2) mface->edcode |= ME_V3V1;
+ if(a & ME_V2V3) mface->edcode |= ME_V1V2;
+ if(a & ME_V3V1) mface->edcode |= ME_V2V3;
+
+ a= mface->puno;
+ mface->puno &= ~15;
+ if(a & ME_FLIPV1) mface->puno |= ME_FLIPV2;
+ if(a & ME_FLIPV2) mface->puno |= ME_FLIPV3;
+ if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
+ }
+ }
+ else if(nr==4) {
+ if(mface->v3==0 || mface->v4==0) {
+ SWAP(int, mface->v1, mface->v3);
+ SWAP(int, mface->v2, mface->v4);
+ a= mface->edcode;
+ mface->edcode= 0;
+ if(a & ME_V1V2) mface->edcode |= ME_V3V4;
+ if(a & ME_V2V3) mface->edcode |= ME_V2V3;
+ if(a & ME_V3V4) mface->edcode |= ME_V1V2;
+ if(a & ME_V4V1) mface->edcode |= ME_V4V1;
+
+ a= mface->puno;
+ mface->puno &= ~15;
+ if(a & ME_FLIPV1) mface->puno |= ME_FLIPV3;
+ if(a & ME_FLIPV2) mface->puno |= ME_FLIPV4;
+ if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
+ if(a & ME_FLIPV4) mface->puno |= ME_FLIPV2;
+ }
+ }
+}
+
+/** This function should die as soon as there is another mesh
+ structure. Functionality is the same as
+
+ void test_index_mface()
+
+ but it fixes texture coordinates as well.
+*/
+
+#define UVCOPY(t, s) memcpy(t, s, 2 * sizeof(float));
+void test_index_face(MFace *mface, TFace *tface, int nr)
+{
+ int a;
+ float tmpuv[2];
+ unsigned int tmpcol;
+
+
+ /* first test if the face is legal */
+
+ if(mface->v3 && mface->v3==mface->v4) {
+ mface->v4= 0;
+ nr--;
+ }
+ if(mface->v2 && mface->v2==mface->v3) {
+ mface->v3= mface->v4;
+ mface->v4= 0;
+ nr--;
+ }
+ if(mface->v1==mface->v2) {
+ mface->v2= mface->v3;
+ mface->v3= mface->v4;
+ mface->v4= 0;
+ nr--;
+ }
+
+ /* voorkom dat een nul op de verkeerde plek staat */
+ if(nr==2) {
+ if(mface->v2==0) SWAP(int, mface->v1, mface->v2);
+ }
+ else if(nr==3) {
+ if(mface->v3==0) {
+ SWAP(int, mface->v1, mface->v2);
+ SWAP(int, mface->v2, mface->v3);
+ /* rotate face UV coordinates, too */
+ UVCOPY(tmpuv, tface->uv[0]);
+ UVCOPY(tface->uv[0], tface->uv[1]);
+ UVCOPY(tface->uv[1], tface->uv[2]);
+ UVCOPY(tface->uv[2], tmpuv);
+ /* same with vertex colours */
+ tmpcol = tface->col[0];
+ tface->col[0] = tface->col[1];
+ tface->col[1] = tface->col[2];
+ tface->col[2] = tmpcol;
+
+
+ a= mface->edcode;
+ mface->edcode= 0;
+ if(a & ME_V1V2) mface->edcode |= ME_V3V1;
+ if(a & ME_V2V3) mface->edcode |= ME_V1V2;
+ if(a & ME_V3V1) mface->edcode |= ME_V2V3;
+
+ a= mface->puno;
+ mface->puno &= ~15;
+ if(a & ME_FLIPV1) mface->puno |= ME_FLIPV2;
+ if(a & ME_FLIPV2) mface->puno |= ME_FLIPV3;
+ if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
+ }
+ }
+ else if(nr==4) {
+ if(mface->v3==0 || mface->v4==0) {
+ SWAP(int, mface->v1, mface->v3);
+ SWAP(int, mface->v2, mface->v4);
+ /* swap UV coordinates */
+ UVCOPY(tmpuv, tface->uv[0]);
+ UVCOPY(tface->uv[0], tface->uv[2]);
+ UVCOPY(tface->uv[2], tmpuv);
+ UVCOPY(tmpuv, tface->uv[1]);
+ UVCOPY(tface->uv[1], tface->uv[3]);
+ UVCOPY(tface->uv[3], tmpuv);
+ /* swap vertex colours */
+ tmpcol = tface->col[0];
+ tface->col[0] = tface->col[2];
+ tface->col[2] = tmpcol;
+ tmpcol = tface->col[1];
+ tface->col[1] = tface->col[3];
+ tface->col[3] = tmpcol;
+
+ a= mface->edcode;
+ mface->edcode= 0;
+ if(a & ME_V1V2) mface->edcode |= ME_V3V4;
+ if(a & ME_V2V3) mface->edcode |= ME_V2V3;
+ if(a & ME_V3V4) mface->edcode |= ME_V1V2;
+ if(a & ME_V4V1) mface->edcode |= ME_V4V1;
+
+ a= mface->puno;
+ mface->puno &= ~15;
+ if(a & ME_FLIPV1) mface->puno |= ME_FLIPV3;
+ if(a & ME_FLIPV2) mface->puno |= ME_FLIPV4;
+ if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
+ if(a & ME_FLIPV4) mface->puno |= ME_FLIPV2;
+ }
+ }
+}
+
+void flipnorm_mesh(Mesh *me)
+{
+ MFace *mface;
+ MVert *mvert;
+ DispList *dl;
+ float *fp;
+ int a, temp;
+
+ mvert= me->mvert;
+ a= me->totvert;
+ while(a--) {
+ mvert->no[0]= -mvert->no[0];
+ mvert->no[1]= -mvert->no[1];
+ mvert->no[2]= -mvert->no[2];
+ mvert++;
+ }
+
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+ if(mface->v3) {
+ if(mface->v4) {
+ SWAP(int, mface->v4, mface->v1);
+ SWAP(int, mface->v3, mface->v2);
+ test_index_mface(mface, 4);
+ temp= mface->puno;
+ mface->puno &= ~15;
+ if(temp & ME_FLIPV1) mface->puno |= ME_FLIPV4;
+ if(temp & ME_FLIPV2) mface->puno |= ME_FLIPV3;
+ if(temp & ME_FLIPV3) mface->puno |= ME_FLIPV2;
+ if(temp & ME_FLIPV4) mface->puno |= ME_FLIPV1;
+ }
+ else {
+ SWAP(int, mface->v3, mface->v1);
+ test_index_mface(mface, 3);
+ temp= mface->puno;
+ mface->puno &= ~15;
+ if(temp & ME_FLIPV1) mface->puno |= ME_FLIPV3;
+ if(temp & ME_FLIPV2) mface->puno |= ME_FLIPV2;
+ if(temp & ME_FLIPV3) mface->puno |= ME_FLIPV1;
+ }
+ }
+ mface++;
+ }
+
+ if(me->disp.first) {
+ dl= me->disp.first;
+ fp= dl->nors;
+ if(fp) {
+ a= dl->nr;
+ while(a--) {
+ fp[0]= -fp[0];
+ fp[1]= -fp[1];
+ fp[2]= -fp[2];
+ fp+= 3;
+ }
+ }
+ }
+}
+
+Mesh *get_mesh(Object *ob)
+{
+
+ if(ob==0) return 0;
+ if(ob->type==OB_MESH) return ob->data;
+ else return 0;
+}
+
+void set_mesh(Object *ob, Mesh *me)
+{
+ Mesh *old=0;
+
+ if(ob==0) return;
+
+ if(ob->type==OB_MESH) {
+ old= ob->data;
+ old->id.us--;
+ ob->data= me;
+ id_us_plus((ID *)me);
+ }
+
+ test_object_materials((ID *)me);
+}
+
+void mball_to_mesh(ListBase *lb, Mesh *me)
+{
+ DispList *dl;
+ MVert *mvert;
+ MFace *mface;
+ float *nors, *verts;
+ int a, *index;
+
+ dl= lb->first;
+ if(dl==0) return;
+
+ if(dl->type==DL_INDEX4) {
+ me->flag= ME_NOPUNOFLIP;
+ me->totvert= dl->nr;
+ me->totface= dl->parts;
+
+ me->mvert=mvert= MEM_callocN(dl->nr*sizeof(MVert), "mverts");
+ a= dl->nr;
+ nors= dl->nors;
+ verts= dl->verts;
+ while(a--) {
+ VECCOPY(mvert->co, verts);
+ mvert->no[0]= (short int)(nors[0]*32767.0);
+ mvert->no[1]= (short int)(nors[1]*32767.0);
+ mvert->no[2]= (short int)(nors[2]*32767.0);
+ mvert++;
+ nors+= 3;
+ verts+= 3;
+ }
+
+ me->mface=mface= MEM_callocN(dl->parts*sizeof(MFace), "mface");
+ a= dl->parts;
+ index= dl->index;
+ while(a--) {
+ mface->v1= index[0];
+ mface->v2= index[1];
+ mface->v3= index[2];
+ mface->v4= index[3];
+
+ mface->puno= 0;
+ mface->edcode= ME_V1V2+ME_V2V3;
+ mface->flag = ME_SMOOTH;
+
+ mface++;
+ index+= 4;
+ }
+ }
+}
+
+void nurbs_to_mesh(Object *ob)
+{
+ Object *ob1;
+ DispList *dl;
+ Mesh *me;
+ Curve *cu;
+ MVert *mvert;
+ MFace *mface;
+ float *data;
+ int a, b, ofs, vertcount, startvert, totvert=0, totvlak=0;
+ int p1, p2, p3, p4, *index;
+
+ cu= ob->data;
+
+ if(ob->type==OB_CURVE) {
+ /* regel: dl->type INDEX3 altijd vooraan in lijst */
+ dl= cu->disp.first;
+ if(dl->type!=DL_INDEX3) {
+ curve_to_filledpoly(ob->data, &cu->disp);
+ }
+ }
+
+ /* tellen */
+ dl= cu->disp.first;
+ while(dl) {
+ if(dl->type==DL_SEGM) {
+ totvert+= dl->parts*dl->nr;
+ totvlak+= dl->parts*(dl->nr-1);
+ }
+ else if(dl->type==DL_POLY) {
+ /* cyclic polys are filled. except when 3D */
+ if(cu->flag & CU_3D) {
+ totvert+= dl->parts*dl->nr;
+ totvlak+= dl->parts*dl->nr;
+ }
+ }
+ else if(dl->type==DL_SURF) {
+ totvert+= dl->parts*dl->nr;
+ totvlak+= (dl->parts-1+((dl->flag & 2)==2))*(dl->nr-1+(dl->flag & 1));
+ }
+ else if(dl->type==DL_INDEX3) {
+ totvert+= dl->nr;
+ totvlak+= dl->parts;
+ }
+ dl= dl->next;
+ }
+ if(totvert==0) {
+ error("can't convert");
+ return;
+ }
+
+ /* mesh maken */
+ me= add_mesh();
+ me->totvert= totvert;
+ me->totface= totvlak;
+
+ me->totcol= cu->totcol;
+ me->mat= cu->mat;
+ cu->mat= 0;
+ cu->totcol= 0;
+
+ mvert=me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "cumesh1");
+ mface=me->mface= MEM_callocN(me->totface*sizeof(MFace), "cumesh2");
+
+ /* verts en vlakken */
+ vertcount= 0;
+
+ dl= cu->disp.first;
+ while(dl) {
+ if(dl->type==DL_SEGM) {
+ startvert= vertcount;
+ a= dl->parts*dl->nr;
+ data= dl->verts;
+ while(a--) {
+ VECCOPY(mvert->co, data);
+ data+=3;
+ vertcount++;
+ mvert++;
+ }
+
+ for(a=0; a<dl->parts; a++) {
+ ofs= a*dl->nr;
+ for(b=1; b<dl->nr; b++) {
+ mface->v1= startvert+ofs+b-1;
+ mface->v2= startvert+ofs+b;
+ mface->edcode= ME_V1V2;
+ test_index_mface(mface, 2);
+ mface++;
+ }
+ }
+
+ }
+ else if(dl->type==DL_POLY) {
+ /* cyclic polys are filled */
+ /* startvert= vertcount;
+ a= dl->parts*dl->nr;
+ data= dl->verts;
+ while(a--) {
+ VECCOPY(mvert->co, data);
+ data+=3;
+ vertcount++;
+ mvert++;
+ }
+
+ for(a=0; a<dl->parts; a++) {
+ ofs= a*dl->nr;
+ for(b=0; b<dl->nr; b++) {
+ mface->v1= startvert+ofs+b;
+ if(b==dl->nr-1) mface->v2= startvert+ofs;
+ else mface->v2= startvert+ofs+b+1;
+ mface->edcode= ME_V1V2;
+ test_index_mface(mface, 2);
+ mface++;
+ }
+ }
+ */
+ }
+ else if(dl->type==DL_INDEX3) {
+ startvert= vertcount;
+ a= dl->nr;
+ data= dl->verts;
+ while(a--) {
+ VECCOPY(mvert->co, data);
+ data+=3;
+ vertcount++;
+ mvert++;
+ }
+
+ a= dl->parts;
+ index= dl->index;
+ while(a--) {
+ mface->v1= startvert+index[0];
+ mface->v2= startvert+index[1];
+ mface->v3= startvert+index[2];
+ mface->v4= 0;
+
+ mface->puno= 7;
+ mface->edcode= ME_V1V2+ME_V2V3;
+ test_index_mface(mface, 3);
+
+ mface++;
+ index+= 3;
+ }
+
+
+ }
+ else if(dl->type==DL_SURF) {
+ startvert= vertcount;
+ a= dl->parts*dl->nr;
+ data= dl->verts;
+ while(a--) {
+ VECCOPY(mvert->co, data);
+ data+=3;
+ vertcount++;
+ mvert++;
+ }
+
+ for(a=0; a<dl->parts; a++) {
+
+ if( (dl->flag & 2)==0 && a==dl->parts-1) break;
+
+ if(dl->flag & 1) { /* p2 -> p1 -> */
+ p1= startvert+ dl->nr*a; /* p4 -> p3 -> */
+ p2= p1+ dl->nr-1; /* -----> volgende rij */
+ p3= p1+ dl->nr;
+ p4= p2+ dl->nr;
+ b= 0;
+ }
+ else {
+ p2= startvert+ dl->nr*a;
+ p1= p2+1;
+ p4= p2+ dl->nr;
+ p3= p1+ dl->nr;
+ b= 1;
+ }
+ if( (dl->flag & 2) && a==dl->parts-1) {
+ p3-= dl->parts*dl->nr;
+ p4-= dl->parts*dl->nr;
+ }
+
+ for(; b<dl->nr; b++) {
+ mface->v1= p1;
+ mface->v2= p3;
+ mface->v3= p4;
+ mface->v4= p2;
+ mface->mat_nr= (unsigned char)dl->col;
+ mface->edcode= ME_V1V2+ME_V2V3;
+ test_index_mface(mface, 4);
+ mface++;
+
+ p4= p3;
+ p3++;
+ p2= p1;
+ p1++;
+ }
+ }
+
+ }
+
+ dl= dl->next;
+ }
+
+ if(ob->data) {
+ free_libblock(&G.main->curve, ob->data);
+ }
+ ob->data= me;
+ ob->type= OB_MESH;
+
+ tex_space_mesh(me);
+
+ /* andere users */
+ ob1= G.main->object.first;
+ while(ob1) {
+ if(ob1->data==cu) {
+ ob1->type= OB_MESH;
+
+ ob1->data= ob->data;
+ id_us_plus((ID *)ob->data);
+ }
+ ob1= ob1->id.next;
+ }
+
+}
+
+void edge_drawflags_mesh(Mesh *me)
+{
+ MFace *mface;
+ int a;
+
+ mface= me->mface;
+ for(a=0; a<me->totface; a++, mface++) {
+ mface->edcode= ME_V1V2|ME_V2V3|ME_V3V4|ME_V4V1;
+ }
+}
+
+void tface_to_mcol(Mesh *me)
+{
+ TFace *tface;
+ unsigned int *mcol;
+ int a;
+
+ me->mcol= MEM_mallocN(4*sizeof(int)*me->totface, "nepmcol");
+ mcol= (unsigned int *)me->mcol;
+
+ a= me->totface;
+ tface= me->tface;
+ while(a--) {
+ memcpy(mcol, tface->col, 16);
+ mcol+= 4;
+ tface++;
+ }
+}
+
+void mcol_to_tface(Mesh *me, int freedata)
+{
+ TFace *tface;
+ unsigned int *mcol;
+ int a;
+
+ a= me->totface;
+ tface= me->tface;
+ mcol= (unsigned int *)me->mcol;
+ while(a--) {
+ memcpy(tface->col, mcol, 16);
+ mcol+= 4;
+ tface++;
+ }
+
+ if(freedata) {
+ MEM_freeN(me->mcol);
+ me->mcol= 0;
+ }
+}
+
+int mesh_uses_displist(Mesh *me) {
+ return (me->flag&ME_SUBSURF && (me->subdiv>0));
+}
+
+int rendermesh_uses_displist(Mesh *me) {
+ return (me->flag&ME_SUBSURF);
+}
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
new file mode 100644
index 00000000000..40851b27c6c
--- /dev/null
+++ b/source/blender/blenkernel/intern/nla.c
@@ -0,0 +1,118 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+
+#include "BKE_nla.h"
+#include "BKE_blender.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_space_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_action_types.h"
+#include "DNA_ID.h"
+#include "DNA_ipo_types.h"
+
+#include "MEM_guardedalloc.h"
+
+void copy_actionstrip (bActionStrip **dst, bActionStrip **src){
+ bActionStrip *dstrip;
+ bActionStrip *sstrip = *src;
+
+ if (!*src){
+ *dst=NULL;
+ return;
+ }
+
+ *dst = MEM_dupallocN(sstrip);
+
+ dstrip = *dst;
+ if (dstrip->act)
+ dstrip->act->id.us++;
+
+ if (dstrip->ipo)
+ dstrip->ipo->id.us++;
+}
+
+void copy_nlastrips (ListBase *dst, ListBase *src)
+{
+ bActionStrip *strip;
+
+ dst->first=dst->last=NULL;
+
+ duplicatelist (dst, src);
+
+ /* Update specific data */
+ if (!dst->first)
+ return;
+
+ for (strip = dst->first; strip; strip=strip->next){
+ if (strip->act)
+ strip->act->id.us++;
+ if (strip->ipo)
+ strip->ipo->id.us++;
+ }
+}
+
+
+void free_actionstrip(bActionStrip* strip)
+{
+ if (!strip)
+ return;
+
+ if (strip->act){
+ strip->act->id.us--;
+ strip->act = NULL;
+ }
+ if (strip->ipo){
+ strip->ipo->id.us--;
+ strip->ipo = NULL;
+ }
+}
+
+void free_nlastrips (ListBase *nlalist)
+{
+ bActionStrip *strip;
+
+ if (!nlalist->first)
+ return;
+
+ /* Do any specific freeing */
+ for (strip=nlalist->first; strip; strip=strip->next)
+ {
+ free_actionstrip (strip);
+ };
+
+ /* Free the whole list */
+ BLI_freelistN(nlalist);
+}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
new file mode 100644
index 00000000000..c6c91d00609
--- /dev/null
+++ b/source/blender/blenkernel/intern/object.c
@@ -0,0 +1,1681 @@
+/* object.c MIXED MODEL
+ *
+ * jan 95
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+
+
+#include <string.h>
+#include <math.h>
+#include <stdio.h>
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_group_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_armature.h"
+#include "BKE_action.h"
+#include "BKE_deform.h"
+#include "BKE_nla.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_bad_level_calls.h"
+
+#include "BKE_main.h"
+#include "BKE_global.h"
+
+#include "BKE_object.h"
+#include "BKE_blender.h"
+#include "BKE_screen.h"
+#include "BKE_ipo.h"
+#include "BKE_ika.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_curve.h"
+#include "BKE_mball.h"
+#include "BKE_effect.h"
+#include "BKE_sca.h"
+#include "BPY_extern.h"
+#include "BKE_displist.h"
+#include "BKE_property.h"
+#include "BKE_anim.h"
+#include "BKE_group.h"
+#include "BKE_lattice.h"
+#include "BKE_constraint.h"
+#include "BKE_scene.h"
+
+/* Local function protos */
+static void solve_parenting (Object *ob, Object *par, float slowmat[][4], int simul);
+
+float originmat[3][3]; /* na where_is_object(), kan her en der gebruikt worden */
+Object workob;
+
+void clear_workob(void)
+{
+ memset(&workob, 0, sizeof(Object));
+
+ workob.size[0]= workob.size[1]= workob.size[2]= 1.0;
+
+}
+
+void copy_baseflags()
+{
+ Base *base= G.scene->base.first;
+
+ while(base) {
+ base->object->flag= base->flag;
+ base= base->next;
+ }
+}
+
+void copy_objectflags()
+{
+ Base *base= G.scene->base.first;
+
+ while(base) {
+ base->flag= base->object->flag;
+ base= base->next;
+ }
+}
+
+void update_base_layer(Object *ob)
+{
+ Base *base= G.scene->base.first;
+
+ while (base) {
+ if (base->object == ob) base->lay= ob->lay;
+ base= base->next;
+ }
+}
+
+/* niet object zelf vrijgeven */
+void free_object(Object *ob)
+{
+ int a;
+
+ /* specifieke data loskoppelen */
+ if(ob->data) {
+ ID *id= ob->data;
+ id->us--;
+ if(id->us==0) {
+ if(ob->type==OB_MESH) unlink_mesh(ob->data);
+ else if(ob->type==OB_CURVE) unlink_curve(ob->data);
+ else if(ob->type==OB_MBALL) unlink_mball(ob->data);
+ }
+ ob->data= 0;
+ }
+
+ for(a=0; a<ob->totcol; a++) {
+ if(ob->mat[a]) ob->mat[a]->id.us--;
+ }
+ if(ob->mat) MEM_freeN(ob->mat);
+ ob->mat= 0;
+ if(ob->bb) MEM_freeN(ob->bb);
+ ob->bb= 0;
+ if(ob->path) free_path(ob->path);
+ ob->path= 0;
+ if(ob->ipo) ob->ipo->id.us--;
+ if(ob->action) ob->action->id.us--;
+ if(ob->defbase.first)
+ BLI_freelistN(&ob->defbase);
+ if(ob->pose) {
+ clear_pose(ob->pose);
+ MEM_freeN(ob->pose);
+ }
+ free_effects(&ob->effect);
+ BLI_freelistN(&ob->network);
+ free_properties(&ob->prop);
+
+ free_sensors(&ob->sensors);
+ free_controllers(&ob->controllers);
+ free_actuators(&ob->actuators);
+
+ free_constraints(&ob->constraints);
+ free_constraint_channels(&ob->constraintChannels);
+ free_nlastrips(&ob->nlastrips);
+
+ freedisplist(&ob->disp);
+
+ BPY_free_scriptlink(&ob->scriptlink);
+}
+
+void unlink_object(Object *ob)
+{
+ Object *obt;
+ Material *mat;
+ World *wrld;
+ bScreen *sc;
+ Scene *sce;
+ Curve *cu;
+ Tex *tex;
+ Group *group;
+ int a;
+
+ unlink_controllers(&ob->controllers);
+ unlink_actuators(&ob->actuators);
+
+ /* alle objecten aflopen: parents en bevels */
+ obt= G.main->object.first;
+ while(obt) {
+ if(obt->id.lib==0) {
+ if(obt->parent==ob) {
+ obt->parent= 0;
+ if(ob->type==OB_LATTICE) freedisplist(&obt->disp);
+ }
+ if(obt->track==ob) obt->track= 0;
+ if ELEM(obt->type, OB_CURVE, OB_FONT) {
+ cu= obt->data;
+ if(cu->bevobj==ob) cu->bevobj= 0;
+ if(cu->textoncurve==ob) cu->textoncurve= 0;
+ }
+ if(obt->type==OB_IKA) {
+ Ika *ika= obt->data;
+ Deform *def= ika->def;
+
+ if(ika->parent==ob) ika->parent= 0;
+ a= ika->totdef;
+ while(a--) {
+ if(def->ob==ob) {
+ ika->totdef= 0;
+ MEM_freeN(ika->def);
+ ika->def= 0;
+ break;
+ }
+ def++;
+ }
+ }
+ sca_remove_ob_poin(obt, ob);
+ }
+ obt= obt->id.next;
+ }
+
+ /* materialen */
+ mat= G.main->mat.first;
+ while(mat) {
+
+ for(a=0; a<8; a++) {
+ if(mat->mtex[a] && ob==mat->mtex[a]->object) {
+ /* eigenlijk testen op lib */
+ mat->mtex[a]->object= 0;
+ }
+ }
+
+ mat= mat->id.next;
+ }
+
+ /* textures */
+ tex= G.main->tex.first;
+ while(tex) {
+ if(tex->env) {
+ if(tex->env->object == ob) tex->env->object= 0;
+ }
+ tex= tex->id.next;
+ }
+
+ /* mballs */
+ if(ob->type==OB_MBALL) {
+ obt= find_basis_mball(ob);
+ if(obt) freedisplist(&obt->disp);
+ }
+
+ /* worlds */
+ wrld= G.main->world.first;
+ while(wrld) {
+ if(wrld->id.lib==0) {
+ for(a=0; a<6; a++) {
+ if(wrld->mtex[a] && ob==wrld->mtex[a]->object)
+ wrld->mtex[a]->object =0;
+ }
+ }
+
+ wrld= wrld->id.next;
+ }
+
+ /* scene's */
+ sce= G.main->scene.first;
+ while(sce) {
+ if(sce->id.lib==0) {
+ if(sce->camera==ob) sce->camera= 0;
+ }
+ sce= sce->id.next;
+ }
+ /* keys */
+
+ /* screens */
+ sc= G.main->screen.first;
+ while(sc) {
+ ScrArea *sa= sc->areabase.first;
+ while(sa) {
+ SpaceLink *sl;
+
+ for (sl= sa->spacedata.first; sl; sl= sl->next) {
+ if(sl->spacetype==SPACE_VIEW3D) {
+ View3D *v3d= (View3D*) sl;
+
+ if(v3d->camera==ob) {
+ v3d->camera= 0;
+ if(v3d->persp>1) v3d->persp= 1;
+ }
+ if(v3d->localvd && v3d->localvd->camera==ob ) {
+ v3d->localvd->camera= 0;
+ if(v3d->localvd->persp>1) v3d->localvd->persp= 1;
+ }
+ }
+ }
+
+ sa= sa->next;
+ }
+ sc= sc->id.next;
+ }
+
+ /* groups */
+ group= G.main->group.first;
+ while(group) {
+ rem_from_group(group, ob);
+ group= group->id.next;
+ }
+}
+
+int exist_object(Object *obtest)
+{
+ Object *ob;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob==obtest) return 1;
+ ob= ob->id.next;
+ }
+ return 0;
+}
+
+void *add_camera()
+{
+ Camera *cam;
+
+ cam= alloc_libblock(&G.main->camera, ID_CA, "Camera");
+
+ cam->lens= 35.0f;
+ cam->clipsta= 0.1f;
+ cam->clipend= 100.0f;
+ cam->drawsize= 0.5f;
+ cam->netsta= 0.5f;
+ cam->netend= 10.0f;
+ cam->hold= 50;
+
+ return cam;
+}
+
+Camera *copy_camera(Camera *cam)
+{
+ Camera *camn;
+
+ camn= copy_libblock(cam);
+ id_us_plus((ID *)camn->ipo);
+
+ BPY_copy_scriptlink(&camn->scriptlink);
+
+ return camn;
+}
+
+
+
+void make_local_camera(Camera *cam)
+{
+ Object *ob;
+ Camera *camn;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(cam->id.lib==0) return;
+ if(cam->id.us==1) {
+ cam->id.lib= 0;
+ cam->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)cam, 0);
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==cam) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ cam->id.lib= 0;
+ cam->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)cam, 0);
+ }
+ else if(local && lib) {
+ camn= copy_camera(cam);
+ camn->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==cam) {
+
+ if(ob->id.lib==0) {
+ ob->data= camn;
+ camn->id.us++;
+ cam->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+
+
+void *add_lamp(void)
+{
+ Lamp *la;
+
+ la= alloc_libblock(&G.main->lamp, ID_LA, "Lamp");
+
+ la->r= la->g= la->b= 1.0;
+ la->haint= la->energy= 1.0;
+ la->dist= 20.0f;
+ la->spotsize= 45.0f;
+ la->spotblend= 0.15f;
+ la->att2= 1.0f;
+ la->mode= LA_SHAD;
+ la->bufsize= 512;
+ la->clipsta= 0.5f;
+ la->clipend= 40.0f;
+ la->shadspotsize= 45.0f;
+ la->samp= 3;
+ la->bias= 1.0f;
+ la->soft= 3.0f;
+
+ return la;
+}
+
+Lamp *copy_lamp(Lamp *la)
+{
+ Lamp *lan;
+ int a;
+
+ lan= copy_libblock(la);
+
+ for(a=0; a<8; a++) {
+ if(lan->mtex[a]) {
+ lan->mtex[a]= MEM_mallocN(sizeof(MTex), "copylamptex");
+ memcpy(lan->mtex[a], la->mtex[a], sizeof(MTex));
+ id_us_plus((ID *)lan->mtex[a]->tex);
+ }
+ }
+
+ id_us_plus((ID *)lan->ipo);
+
+ BPY_copy_scriptlink(&la->scriptlink);
+
+ return lan;
+}
+
+void make_local_lamp(Lamp *la)
+{
+ Object *ob;
+ Lamp *lan;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(la->id.lib==0) return;
+ if(la->id.us==1) {
+ la->id.lib= 0;
+ la->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)la, 0);
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==la) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ la->id.lib= 0;
+ la->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)la, 0);
+ }
+ else if(local && lib) {
+ lan= copy_lamp(la);
+ lan->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==la) {
+
+ if(ob->id.lib==0) {
+ ob->data= lan;
+ lan->id.us++;
+ la->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+void free_camera(Camera *ca)
+{
+ BPY_free_scriptlink(&ca->scriptlink);
+}
+
+void free_lamp(Lamp *la)
+{
+ MTex *mtex;
+ int a;
+
+ /* scriptlinks */
+
+ BPY_free_scriptlink(&la->scriptlink);
+
+ for(a=0; a<8; a++) {
+ mtex= la->mtex[a];
+ if(mtex && mtex->tex) mtex->tex->id.us--;
+ if(mtex) MEM_freeN(mtex);
+ }
+ la->ipo= 0;
+}
+
+void *add_wave()
+{
+ return 0;
+}
+
+
+/* *************************************************** */
+
+static void *add_obdata_from_type(int type)
+{
+ switch (type) {
+ case OB_MESH: G.totmesh++; return add_mesh();
+ case OB_CURVE: G.totcurve++; return add_curve(OB_CURVE);
+ case OB_SURF: G.totcurve++; return add_curve(OB_SURF);
+ case OB_FONT: return add_curve(OB_FONT);
+ case OB_MBALL: return add_mball();
+ case OB_CAMERA: return add_camera();
+ case OB_LAMP: G.totlamp++; return add_lamp();
+ case OB_IKA: return add_ika();
+ case OB_LATTICE: return add_lattice();
+ case OB_WAVE: return add_wave();
+ case OB_ARMATURE: return add_armature();
+ case OB_EMPTY: return NULL;
+ default:
+ printf("add_obdata_from_type: Internal error, bad type: %d\n", type);
+ return NULL;
+ }
+}
+
+static char *get_obdata_defname(int type)
+{
+ switch (type) {
+ case OB_MESH: return "Mesh";
+ case OB_CURVE: return "Curve";
+ case OB_SURF: return "Surf";
+ case OB_FONT: return "Font";
+ case OB_MBALL: return "Mball";
+ case OB_CAMERA: return "Camera";
+ case OB_LAMP: return "Lamp";
+ case OB_IKA: return "Ika";
+ case OB_LATTICE: return "Lattice";
+ case OB_WAVE: return "Wave";
+ case OB_ARMATURE: return "Armature";
+ case OB_EMPTY: return "Empty";
+ default:
+ printf("get_obdata_defname: Internal error, bad type: %d\n", type);
+ return "Empty";
+ }
+}
+
+/* algemene add: in G.scene, met layer uit area en default naam */
+/* maakt alle minimaal nodige datablokken aan, zonder vertices etc. */
+Object *add_object(int type)
+{
+ Object *ob;
+ Base *base;
+ char name[32];
+
+ if (G.obpose)
+ exit_posemode(1);
+
+ strcpy(name, get_obdata_defname(type));
+
+ ob= alloc_libblock(&G.main->object, ID_OB, name);
+ G.totobj++;
+
+ /* default object vars */
+ ob->type= type;
+ /* ob->transflag= OB_QUAT; */
+
+ QuatOne(ob->quat);
+ QuatOne(ob->dquat);
+
+ ob->col[0]= ob->col[1]= ob->col[2]= 0.0;
+ ob->col[3]= 1.0;
+
+ ob->loc[0]= ob->loc[1]= ob->loc[2]= 0.0;
+ ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0;
+ ob->size[0]= ob->size[1]= ob->size[2]= 1.0;
+
+ Mat4One(ob->parentinv);
+ Mat4One(ob->obmat);
+ ob->dt= OB_SHADED;
+ if(U.flag & MAT_ON_OB) ob->colbits= -1;
+
+ if(type==OB_CAMERA || type==OB_LAMP) {
+ ob->trackflag= OB_NEGZ;
+ ob->upflag= OB_POSY;
+ }
+ else {
+ ob->trackflag= OB_POSY;
+ ob->upflag= OB_POSZ;
+ }
+ ob->ipoflag = OB_OFFS_OB+OB_OFFS_PARENT;
+
+ ob->dupon= 1; ob->dupoff= 0;
+ ob->dupsta= 1; ob->dupend= 100;
+
+ /* Gameengine defaults*/
+ ob->mass= ob->inertia= 1.0f;
+ ob->formfactor= 0.4f;
+ ob->damping= 0.04f;
+ ob->rdamping= 0.1f;
+ ob->anisotropicFriction[0] = 1.0f;
+ ob->anisotropicFriction[1] = 1.0f;
+ ob->anisotropicFriction[2] = 1.0f;
+ ob->gameflag= OB_PROP;
+
+ ob->data= add_obdata_from_type(type);
+
+ ob->lay= G.scene->lay;
+
+ base= scene_add_base(G.scene, ob);
+ scene_select_base(G.scene, base);
+
+ return ob;
+}
+
+void base_init_from_view3d(Base *base, View3D *v3d)
+{
+ Object *ob= base->object;
+
+ if (v3d->localview) {
+ base->lay= ob->lay= v3d->layact + v3d->lay;
+ VECCOPY(ob->loc, v3d->cursor);
+ } else {
+ base->lay= ob->lay= v3d->layact;
+ VECCOPY(ob->loc, G.scene->cursor);
+ }
+
+ v3d->viewquat[0]= -v3d->viewquat[0];
+ if (ob->transflag & OB_QUAT) {
+ QUATCOPY(ob->quat, v3d->viewquat);
+ } else {
+ QuatToEul(v3d->viewquat, ob->rot);
+ }
+ v3d->viewquat[0]= -v3d->viewquat[0];
+}
+
+Object *copy_object(Object *ob)
+{
+ Object *obn;
+ int a;
+ bConstraintChannel *actcon;
+
+ obn= copy_libblock(ob);
+
+ if(ob->totcol) {
+ obn->mat= MEM_dupallocN(ob->mat);
+ }
+
+ if(ob->bb) obn->bb= MEM_dupallocN(ob->bb);
+ obn->path= 0;
+ obn->flag &= ~OB_FROMGROUP;
+
+ copy_effects(&obn->effect, &ob->effect);
+
+ obn->network.first= obn->network.last= 0;
+
+ BPY_copy_scriptlink(&ob->scriptlink);
+
+ copy_properties(&obn->prop, &ob->prop);
+ copy_sensors(&obn->sensors, &ob->sensors);
+ copy_controllers(&obn->controllers, &ob->controllers);
+ copy_actuators(&obn->actuators, &ob->actuators);
+
+ copy_pose(&obn->pose, ob->pose, 1);
+ copy_defgroups(&obn->defbase, &ob->defbase);
+ copy_nlastrips(&obn->nlastrips, &ob->nlastrips);
+ copy_constraints (&obn->constraints, &ob->constraints);
+
+ actcon = clone_constraint_channels (&obn->constraintChannels, &ob->constraintChannels, ob->activecon);
+ /* If the active constraint channel was in this list, update it */
+ if (actcon)
+ obn->activecon = actcon;
+
+ /* usernummers ophogen */
+ id_us_plus((ID *)obn->data);
+ id_us_plus((ID *)obn->ipo);
+ id_us_plus((ID *)obn->action);
+ for(a=0; a<obn->totcol; a++) id_us_plus((ID *)obn->mat[a]);
+
+ obn->disp.first= obn->disp.last= 0;
+
+ return obn;
+}
+
+void expand_local_object(Object *ob)
+{
+ int a;
+
+ id_lib_extern((ID *)ob->action);
+ id_lib_extern((ID *)ob->ipo);
+ id_lib_extern((ID *)ob->data);
+
+ for(a=0; a<ob->totcol; a++) {
+ id_lib_extern((ID *)ob->mat[a]);
+ }
+}
+
+void make_local_object(Object *ob)
+{
+ Object *obn;
+ Scene *sce;
+ Base *base;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(ob->id.lib==0) return;
+ if(ob->id.us==1) {
+ ob->id.lib= 0;
+ ob->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ob, 0);
+
+ }
+ else {
+ sce= G.main->scene.first;
+ while(sce) {
+ base= sce->base.first;
+ while(base) {
+ if(base->object==ob) {
+ if(sce->id.lib) lib++;
+ else local++;
+ break;
+ }
+ base= base->next;
+ }
+ sce= sce->id.next;
+ }
+
+ if(local && lib==0) {
+ ob->id.lib= 0;
+ ob->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ob, 0);
+ }
+ else if(local && lib) {
+ obn= copy_object(ob);
+ obn->id.us= 0;
+
+ sce= G.main->scene.first;
+ while(sce) {
+ if(sce->id.lib==0) {
+ base= sce->base.first;
+ while(base) {
+ if(base->object==ob) {
+ base->object= obn;
+ obn->id.us++;
+ ob->id.us--;
+ }
+ base= base->next;
+ }
+ }
+ sce= sce->id.next;
+ }
+ }
+ }
+
+ expand_local_object(ob);
+}
+
+/* *************** CALC ****************** */
+
+/* er zit ook een tijdberekening in de drawobject() */
+
+float bluroffs= 0.0;
+int no_speed_curve= 0;
+
+void set_mblur_offs(int blur)
+{
+ bluroffs= R.r.blurfac*((float)blur);
+ bluroffs/= (float)R.r.osa;
+}
+
+void disable_speed_curve(int val)
+{
+ no_speed_curve= val;
+}
+
+float bsystem_time(Object *ob, Object *par, float cfra, float ofs)
+{
+ /* geeft float terug ( zie ook frame_to_float in ipo.c) */
+
+ if(no_speed_curve==0) if(ob && ob->ipo) cfra= calc_ipo_time(ob->ipo, cfra);
+
+ /* tweede field */
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_FIELDSTILL); else cfra+= .5;
+ }
+
+ /* motion blur */
+ cfra+= bluroffs;
+
+ /* global time */
+ cfra*= G.scene->r.framelen;
+
+ /* ofset frames */
+ if(ob && (ob->ipoflag & OB_OFFS_PARENT)) {
+ if((ob->partype & PARSLOW)==0) cfra-= ob->sf;
+ }
+
+ cfra-= ofs;
+
+ return cfra;
+}
+
+void object_to_mat3(Object *ob, float mat[][3]) /* no parent */
+{
+ float smat[3][3], vec[3];
+ float rmat[3][3];
+ float q1[4];
+
+ /* size */
+ if(ob->ipo) {
+ vec[0]= ob->size[0]+ob->dsize[0];
+ vec[1]= ob->size[1]+ob->dsize[1];
+ vec[2]= ob->size[2]+ob->dsize[2];
+ SizeToMat3(vec, smat);
+ }
+ else {
+ SizeToMat3(ob->size, smat);
+ }
+
+ /* rot */
+ if(ob->transflag & OB_QUAT) {
+ if(ob->ipo) {
+ QuatMul(q1, ob->quat, ob->dquat);
+ QuatToMat3(q1, rmat);
+ }
+ else {
+ QuatToMat3(ob->quat, rmat);
+ }
+ }
+ else {
+ if(ob->ipo) {
+ vec[0]= ob->rot[0]+ob->drot[0];
+ vec[1]= ob->rot[1]+ob->drot[1];
+ vec[2]= ob->rot[2]+ob->drot[2];
+ EulToMat3(vec, rmat);
+ }
+ else {
+ EulToMat3(ob->rot, rmat);
+ }
+ }
+ Mat3MulMat3(mat, rmat, smat);
+}
+
+void object_to_mat4(Object *ob, float mat[][4])
+{
+ float tmat[3][3];
+
+ object_to_mat3(ob, tmat);
+
+ Mat4CpyMat3(mat, tmat);
+
+ VECCOPY(mat[3], ob->loc);
+ if(ob->ipo) {
+ mat[3][0]+= ob->dloc[0];
+ mat[3][1]+= ob->dloc[1];
+ mat[3][2]+= ob->dloc[2];
+ }
+}
+
+int enable_cu_speed= 1;
+
+void ob_parcurve(Object *ob, Object *par, float mat[][4])
+{
+ Curve *cu;
+ float q[4], vec[4], dir[3], *quat, x1, ctime;
+
+ Mat4One(mat);
+
+ cu= par->data;
+ if(cu->path==0 || cu->path->data==0) calc_curvepath(par);
+ if(cu->path==0) return;
+
+ /* uitzondering afvangen: curve paden die als duplicator worden gebruikt */
+ if(enable_cu_speed) {
+ ctime= bsystem_time(ob, par, (float)G.scene->r.cfra, 0.0);
+
+ if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) {
+ ctime /= cu->pathlen;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+ }
+ else {
+ ctime= G.scene->r.cfra - ob->sf;
+ ctime /= cu->pathlen;
+
+ CLAMP(ctime, 0.0, 1.0);
+ }
+
+ if( where_on_path(par, ctime, vec, dir) ) {
+
+ if(cu->flag & CU_FOLLOW) {
+ quat= vectoquat(dir, ob->trackflag, ob->upflag);
+
+ Normalise(dir);
+ q[0]= (float)cos(0.5*vec[3]);
+ x1= (float)sin(0.5*vec[3]);
+ q[1]= -x1*dir[0];
+ q[2]= -x1*dir[1];
+ q[3]= -x1*dir[2];
+ QuatMul(quat, q, quat);
+
+ QuatToMat4(quat, mat);
+ }
+
+ VECCOPY(mat[3], vec);
+
+ }
+}
+
+void ob_parbone(Object *ob, Object *par, float mat[][4])
+{
+ Bone *bone;
+ bArmature *arm;
+
+ Mat4One(mat);
+ arm=get_armature(par);
+ if (!arm)
+ return;
+
+ /* Make sure the bone is still valid */
+ bone = get_named_bone(arm, ob->parsubstr);
+ if (!bone){
+ printf ("Lost bone %s\n", ob->parsubstr);
+ return;
+ }
+
+ apply_pose_armature(arm, par->pose, 1); /* Hopefully can set doit parameter in the future */
+ where_is_bone (par, bone);
+
+ /* Translate by negative bone */
+ get_objectspace_bone_matrix(bone, mat, 0, 1);
+
+}
+
+void ob_parlimb(Object *ob, Object *par, float mat[][4])
+{
+ Ika *ika;
+ Limb *li;
+ float ang=0.0;
+ int cur=0;
+
+ /* in lokale ob space */
+ Mat4One(mat);
+
+ ika= par->data;
+ li= ika->limbbase.first;
+ while(li) {
+ ang+= li->alpha;
+ if(cur==ob->par1 || li->next==0) break;
+
+ cur++;
+ li= li->next;
+ }
+
+ mat[0][0]= (float)cos(ang);
+ mat[1][0]= (float)-sin(ang);
+ mat[0][1]= (float)sin(ang);
+ mat[1][1]= (float)cos(ang);
+
+ mat[3][0]= li->eff[0];
+ mat[3][1]= li->eff[1];
+
+}
+
+void give_parvert(Object *par, int nr, float *vec)
+{
+ Mesh *me;
+ MVert *mvert;
+ EditVert *eve;
+/* extern ListBase editNurb; already in bad lev calls */
+ Nurb *nu;
+ Curve *cu;
+ BPoint *bp;
+ DispList *dl;
+ BezTriple *bezt;
+ float *fp;
+ int a, count;
+
+ vec[0]=vec[1]=vec[2]= 0.0;
+
+ if(par->type==OB_MESH) {
+ if(par==G.obedit) {
+ if(nr >= G.totvert) nr= 0;
+
+ count= 0;
+ eve= G.edve.first;
+ while(eve) {
+ if(count==nr) {
+ memcpy(vec, eve->co, 12);
+ break;
+ }
+ eve= eve->next;
+ count++;
+ }
+ }
+ else {
+ me= par->data;
+ if(me->totvert) {
+ if(nr >= me->totvert) nr= 0;
+
+ /* is er deform */
+ dl= find_displist(&par->disp, DL_VERTS);
+ if(dl) {
+ fp= dl->verts+3*nr;
+ VECCOPY(vec, fp);
+ }
+ else {
+ mvert= me->mvert + nr;
+ VECCOPY(vec, mvert->co);
+ }
+ }
+ }
+ }
+ else if ELEM(par->type, OB_CURVE, OB_SURF) {
+
+ cu= par->data;
+ nu= cu->nurb.first;
+ if(par==G.obedit) nu= editNurb.first;
+
+ count= 0;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(count==nr) {
+ VECCOPY(vec, bezt->vec[1]);
+ break;
+ }
+ count++;
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(count==nr) {
+ memcpy(vec, bp->vec, 12);
+ break;
+ }
+ count++;
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+
+ }
+ else if(par->type==OB_IKA) {
+ Ika *ika= par->data;
+ Limb *li= ika->limbbase.first;
+ int cur= 1;
+ if(nr) {
+ while(li) {
+ if(cur==nr || li->next==0) break;
+ cur++;
+ li= li->next;
+ }
+ vec[0]= li->eff[0];
+ vec[1]= li->eff[1];
+ }
+ }
+ else return;
+}
+
+void ob_parvert3(Object *ob, Object *par, float mat[][4])
+{
+ float cmat[3][3], v1[3], v2[3], v3[3], q[4];
+
+ /* in lokale ob space */
+ Mat4One(mat);
+
+ if ELEM3(par->type, OB_MESH, OB_SURF, OB_CURVE) {
+
+ give_parvert(par, ob->par1, v1);
+ give_parvert(par, ob->par2, v2);
+ give_parvert(par, ob->par3, v3);
+
+ triatoquat(v1, v2, v3, q);
+ QuatToMat3(q, cmat);
+ Mat4CpyMat3(mat, cmat);
+
+ if(ob->type==OB_CURVE) {
+ VECCOPY(mat[3], v1);
+ }
+ else {
+ VecAddf(mat[3], v1, v2);
+ VecAddf(mat[3], mat[3], v3);
+ VecMulf(mat[3], 0.3333333f);
+ }
+ }
+}
+
+static int no_parent_ipo=0;
+void set_no_parent_ipo(int val)
+{
+ no_parent_ipo= val;
+}
+
+static float timefac= 1.0; /* 50 Hz, dtime:2 */
+void set_dtime(int dtime)
+{
+ timefac= ((float)(dtime-1))/2.0f;
+}
+
+static int during_script_flag=0;
+void disable_where_script(short on)
+{
+ during_script_flag= on;
+}
+
+int during_script(void) {
+ return during_script_flag;
+}
+
+void where_is_object_time(Object *ob, float ctime)
+{
+ Object *par;
+ float *fp1, *fp2, slowmat[4][4] = MAT4_UNITY;
+ float stime, fac1, fac2;
+ int a;
+ int pop;
+
+ /* nieuwe versie: correcte parent+vertexparent en track+parent */
+ /* deze berekent alleen de directe relatie met de parent en track */
+ /* hij is sneller, maar moet wel de timeoffs in de gaten houden */
+
+ if(ob==0) return;
+
+ if( ctime != ob->ctime) {
+ ob->ctime= ctime;
+
+ if(ob->ipo) {
+
+ stime= bsystem_time(ob, 0, ctime, 0.0);
+
+ calc_ipo(ob->ipo, stime);
+ execute_ipo((ID *)ob, ob->ipo);
+ }
+ }
+
+
+ if(ob->type==OB_IKA) {
+ Ika *ika= ob->data;
+ if(ika->parent) where_is_object_time(ika->parent, ctime);
+ }
+
+ if(ob->parent) {
+ par= ob->parent;
+
+ if(ob->ipoflag & OB_OFFS_PARENT) ctime-= ob->sf;
+
+ pop= 0;
+ if(no_parent_ipo==0 && ctime != par->ctime) {
+
+ // alleen voor ipo systemen?
+ pushdata(par, sizeof(Object));
+ pop= 1;
+
+ where_is_object_time(par, ctime);
+ }
+
+ solve_parenting(ob, par, slowmat, 0);
+
+ if(pop) {
+ poplast(par);
+ }
+
+ if(ob->partype & PARSLOW) {
+ // framerate meetellen
+
+ fac1= (float)(timefac/(1.0+ fabs(ob->sf)));
+ if(fac1>=1.0) return;
+ fac2= 1.0f-fac1;
+
+ fp1= ob->obmat[0];
+ fp2= slowmat[0];
+ for(a=0; a<16; a++, fp1++, fp2++) {
+ fp1[0]= fac1*fp1[0] + fac2*fp2[0];
+ }
+ }
+
+ }
+ else {
+ object_to_mat4(ob, ob->obmat);
+ }
+
+ /* Handle tracking */
+ if(ob->track) {
+ if( ctime != ob->track->ctime) where_is_object_time(ob->track, ctime);
+ solve_tracking (ob, ob->track->obmat);
+
+ }
+
+ solve_constraints (ob, TARGET_OBJECT, NULL, ctime);
+
+ if(ob->scriptlink.totscript && !during_script()) {
+ BPY_do_pyscript((ID *)ob, SCRIPT_REDRAW);
+ }
+}
+
+static void solve_parenting (Object *ob, Object *par, float slowmat[][4], int simul)
+{
+ float totmat[4][4];
+ float tmat[4][4];
+ float obmat[4][4];
+ float vec[3];
+ int ok;
+
+ object_to_mat4(ob, obmat);
+
+ if(ob->partype & PARSLOW) Mat4CpyMat4(slowmat, ob->obmat);
+
+
+ switch(ob->partype & PARTYPE) {
+ case PAROBJECT:
+ ok= 0;
+ if(par->type==OB_CURVE) {
+ if( ((Curve *)par->data)->flag & CU_PATH ) {
+ ob_parcurve(ob, par, tmat);
+ ok= 1;
+ }
+ }
+
+ if(ok) Mat4MulSerie(totmat, par->obmat, tmat,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ else Mat4CpyMat4(totmat, par->obmat);
+
+ break;
+ case PARBONE:
+ ob_parbone(ob, par, tmat);
+ Mat4MulSerie(totmat, par->obmat, tmat,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ break;
+ case PARLIMB:
+ ob_parlimb(ob, par, tmat);
+ Mat4MulSerie(totmat, par->obmat, tmat,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ break;
+
+ case PARVERT1:
+ Mat4One(totmat);
+ if (simul){
+ VECCOPY(totmat[3], par->obmat[3]);
+ }
+ else{
+ give_parvert(par, ob->par1, vec);
+ VecMat4MulVecfl(totmat[3], par->obmat, vec);
+ }
+ break;
+ case PARVERT3:
+ ob_parvert3(ob, par, tmat);
+
+ Mat4MulSerie(totmat, par->obmat, tmat,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ break;
+
+ case PARSKEL:
+#if 0
+ if (ob!=G.obedit)
+ Mat4One(totmat);
+ else
+ Mat4CpyMat4(totmat, par->obmat);
+ break;
+#else
+ Mat4CpyMat4(totmat, par->obmat);
+#endif
+ }
+
+ // totaal
+ Mat4MulSerie(tmat, totmat, ob->parentinv,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ Mat4MulSerie(ob->obmat, tmat, obmat,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+
+ if (simul){
+
+ }
+ else{
+ // >>>>>>>>>>>>>>>>>>
+ // dit is een extern bruikbare originmat
+ Mat3CpyMat4(originmat, tmat);
+
+ // origin, voor hulplijntje
+ if( (ob->partype & 15)==PARSKEL ) {
+ VECCOPY(ob->orig, par->obmat[3]);
+ }
+ else {
+ VECCOPY(ob->orig, totmat[3]);
+ }
+ }
+
+}
+void solve_tracking (Object *ob, float targetmat[][4])
+{
+ float *quat;
+ float vec[3];
+ float totmat[3][3];
+ float tmat[4][4];
+
+ VecSubf(vec, ob->obmat[3], targetmat[3]);
+ quat= vectoquat(vec, ob->trackflag, ob->upflag);
+ QuatToMat3(quat, totmat);
+
+ if(ob->parent && (ob->transflag & OB_POWERTRACK)) {
+ /* 'tijdelijk' : parent info wissen */
+ object_to_mat4(ob, tmat);
+ tmat[0][3]= ob->obmat[0][3];
+ tmat[1][3]= ob->obmat[1][3];
+ tmat[2][3]= ob->obmat[2][3];
+ tmat[3][0]= ob->obmat[3][0];
+ tmat[3][1]= ob->obmat[3][1];
+ tmat[3][2]= ob->obmat[3][2];
+ tmat[3][3]= ob->obmat[3][3];
+ }
+ else Mat4CpyMat4(tmat, ob->obmat);
+
+ Mat4MulMat34(ob->obmat, totmat, tmat);
+
+}
+
+void where_is_object(Object *ob)
+{
+
+ /* deze zijn gememcopied */
+ if(ob->flag & OB_FROMDUPLI) return;
+
+ where_is_object_time(ob, (float)G.scene->r.cfra);
+}
+
+
+void where_is_object_simul(Object *ob)
+/* It seems that this function is only called
+for a lamp that is the child of another object */
+{
+ Object *par;
+ Ipo *ipo;
+ float *fp1, *fp2;
+ float slowmat[4][4];
+ float fac1, fac2;
+ int a;
+
+ /* nieuwe versie: correcte parent+vertexparent en track+parent */
+ /* deze berekent alleen de directe relatie met de parent en track */
+ /* GEEN TIMEOFFS */
+
+ /* geen ipo! (ivm dloc en realtime-ipos) */
+ ipo= ob->ipo;
+ ob->ipo= NULL;
+
+ if(ob->parent) {
+ par= ob->parent;
+
+ solve_parenting(ob, par, slowmat, 1);
+
+ if(ob->partype & PARSLOW) {
+
+ fac1= (float)(1.0/(1.0+ fabs(ob->sf)));
+ fac2= 1.0f-fac1;
+ fp1= ob->obmat[0];
+ fp2= slowmat[0];
+ for(a=0; a<16; a++, fp1++, fp2++) {
+ fp1[0]= fac1*fp1[0] + fac2*fp2[0];
+ }
+ }
+
+ }
+ else {
+ object_to_mat4(ob, ob->obmat);
+ }
+
+ if(ob->track)
+ solve_tracking(ob, ob->track->obmat);
+
+ solve_constraints(ob, TARGET_OBJECT, NULL, G.scene->r.cfra);
+
+ /* LET OP!!! */
+ ob->ipo= ipo;
+
+}
+extern void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight);
+
+void solve_constraints (Object *ob, short obtype, void *obdata, float ctime)
+{
+ bConstraint *con;
+ float tmat[4][4], focusmat[4][4], lastmat[4][4];
+ int i, clear=1, tot=0;
+ float a;
+ float aquat[4], quat[4];
+ float aloc[3], loc[3];
+ float asize[3], size[3];
+ float oldmat[4][4];
+ float smat[3][3], rmat[3][3], mat[3][3];
+ float enf;
+
+ for (con = ob->constraints.first; con; con=con->next){
+ /* Clear accumulators if necessary*/
+ if (clear){
+ clear=0;
+ a=0;
+ tot=0;
+ memset(aquat, 0, sizeof(float)*4);
+ memset(aloc, 0, sizeof(float)*3);
+ memset(asize, 0, sizeof(float)*3);
+ }
+
+ /* Check this constraint only if it has some enforcement */
+ // if (con->enforce > 0)
+ if (!(con->flag & CONSTRAINT_DISABLE))
+ {
+ if (con->enforce==0)
+ enf = 0.001f;
+ enf = con->enforce;
+
+ /* Get the targetmat */
+ get_constraint_target(con, obtype, obdata, tmat, size, ctime);
+
+ Mat4CpyMat4(focusmat, tmat);
+
+ /* Extract the components & accumulate */
+ Mat4ToQuat(focusmat, quat);
+ VECCOPY(loc, focusmat[3]);
+
+ a+=enf;
+ tot++;
+
+ for(i=0; i<3; i++){
+ aquat[i+1]+=(quat[i+1]) * enf;
+ aloc[i]+=(loc[i]) * enf;
+ asize[i]+=(size[i]-1.0f) * enf;
+ }
+ aquat[0]+=(quat[0])*enf;
+ Mat4CpyMat4(lastmat, focusmat);
+ }
+
+ /* If the next constraint is not the same type (or there isn't one),
+ * then evaluate the accumulator & request a clear */
+ if ((!con->next)||(con->next && con->next->type!=con->type))
+ {
+ clear=1;
+ Mat4CpyMat4(oldmat, ob->obmat);
+
+ /* If we have several inputs, do a blend of them */
+ if (tot){
+ if (tot>1){
+ if (a){
+ for (i=0; i<3; i++){
+ asize[i]=1.0f + (asize[i]/(a));
+ aloc[i]=(aloc[i]/a);
+ }
+
+ NormalQuat(aquat);
+
+ QuatToMat3(aquat, rmat);
+ SizeToMat3(asize, smat);
+ Mat3MulMat3(mat, rmat, smat);
+ Mat4CpyMat3(focusmat, mat);
+ VECCOPY(focusmat[3], aloc);
+
+ evaluate_constraint(con, ob, obtype, obdata, focusmat);
+ }
+
+ }
+ /* If we only have one, blend with the current obmat */
+ else{
+ float solution[4][4];
+ float delta[4][4];
+ float imat[4][4];
+ float identity[4][4];
+ float worldmat[4][4];
+
+ if (con->type!=CONSTRAINT_TYPE_KINEMATIC){
+ /* If we're not an IK constraint, solve the constraint then blend it to the previous one */
+ evaluate_constraint(con, ob, obtype, obdata, lastmat);
+
+ Mat4CpyMat4 (solution, ob->obmat);
+
+ /* Interpolate the enforcement */
+ Mat4Invert (imat, oldmat);
+ Mat4MulMat4 (delta, solution, imat);
+
+ Mat4One(identity);
+ Mat4BlendMat4(delta, identity, delta, a);
+ Mat4MulMat4 (ob->obmat, delta, oldmat);
+
+ }
+ else{
+ /* Interpolate the target between the chain's unconstrained endpoint and the effector loc */
+ if (obtype==TARGET_BONE){
+ get_objectspace_bone_matrix(obdata, oldmat, 1, 1);
+
+ Mat4MulMat4(worldmat, oldmat, ob->parent->obmat);
+
+ Mat4BlendMat4(focusmat, worldmat, lastmat, a);
+
+ evaluate_constraint(con, ob, obtype, obdata, focusmat);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+void what_does_parent1(Object *par, int partype, int par1, int par2, int par3)
+{
+
+ clear_workob();
+ Mat4One(workob.parentinv);
+ workob.parent= par;
+ if(par)
+ workob.track= par->track; /* LET OP: NIET ECHT NETJES */
+ workob.partype= partype;
+ workob.par1= par1;
+ workob.par2= par2;
+ workob.par3= par3;
+
+ if (par){
+ workob.constraints.first = par->constraints.first;
+ workob.constraints.last = par->constraints.last;
+ }
+
+ where_is_object(&workob);
+}
+
+
+void what_does_parent(Object *ob)
+{
+
+ clear_workob();
+ Mat4One(workob.obmat);
+ Mat4One(workob.parentinv);
+ workob.parent= ob->parent;
+ workob.track= ob->track;
+
+ workob.trackflag= ob->trackflag;
+ workob.upflag= ob->upflag;
+
+ workob.partype= ob->partype;
+ workob.par1= ob->par1;
+ workob.par2= ob->par2;
+ workob.par3= ob->par3;
+
+ workob.constraints.first = ob->constraints.first;
+ workob.constraints.last = ob->constraints.last;
+
+ strcpy (workob.parsubstr, ob->parsubstr);
+
+ where_is_object(&workob);
+}
+
+BoundBox *unit_boundbox()
+{
+ BoundBox *bb;
+
+ bb= MEM_mallocN(sizeof(BoundBox), "bb");
+
+ bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= -1.0;
+ bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= 1.0;
+
+ bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= -1.0;
+ bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= 1.0;
+
+ bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= -1.0;
+ bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= 1.0;
+
+ return bb;
+}
+
+void minmax_object(Object *ob, float *min, float *max)
+{
+ BoundBox bb;
+ Mesh *me;
+ Curve *cu;
+ float vec[3];
+ int a;
+
+ switch(ob->type) {
+
+ case OB_CURVE:
+ case OB_FONT:
+ case OB_SURF:
+ cu= ob->data;
+
+ if(cu->bb==0) tex_space_curve(cu);
+ bb= *(cu->bb);
+
+ for(a=0; a<8; a++) {
+ Mat4MulVecfl(ob->obmat, bb.vec[a]);
+ DO_MINMAX(bb.vec[a], min, max);
+ }
+ break;
+
+ case OB_MESH:
+ me= get_mesh(ob);
+
+ if(me) {
+ if(me->bb==0) tex_space_mesh(me);
+ bb= *(me->bb);
+
+ for(a=0; a<8; a++) {
+ Mat4MulVecfl(ob->obmat, bb.vec[a]);
+ DO_MINMAX(bb.vec[a], min, max);
+ }
+ }
+ if(min[0] < max[0] ) break;
+
+ /* else here no break!!!, mesh can be zero sized */
+
+ default:
+ DO_MINMAX(ob->obmat[3], min, max);
+
+ VECCOPY(vec, ob->obmat[3]);
+ VecAddf(vec, vec, ob->size);
+ DO_MINMAX(vec, min, max);
+
+ VECCOPY(vec, ob->obmat[3]);
+ VecSubf(vec, vec, ob->size);
+ DO_MINMAX(vec, min, max);
+ break;
+ }
+}
+
+
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
new file mode 100644
index 00000000000..991b4a8c840
--- /dev/null
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -0,0 +1,638 @@
+/**
+ * blenkernel/packedFile.c - (cleaned up mar-01 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+#include <string.h>
+#include "MEM_guardedalloc.h"
+
+#include "DNA_image_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_packedFile_types.h"
+
+
+#include "BLI_blenlib.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_bad_level_calls.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BKE_screen.h"
+
+#include "BKE_sound.h"
+//#include "sound.h"
+
+#include "BKE_image.h"
+#include "BKE_font.h"
+#include "BKE_packedFile.h"
+
+int seekPackedFile(PackedFile * pf, int offset, int whence)
+{
+ int oldseek = -1, seek = 0;
+
+ if (pf) {
+ oldseek = pf->seek;
+ switch(whence) {
+ case SEEK_CUR:
+ seek = oldseek + offset;
+ break;
+ case SEEK_END:
+ seek = pf->size + offset;
+ break;
+ case SEEK_SET:
+ seek = offset;
+ break;
+ default:
+ oldseek = -1;
+ }
+ if (seek < 0) {
+ seek = 0;
+ } else if (seek > pf->size) {
+ seek = pf->size;
+ }
+ pf->seek = seek;
+ }
+
+ return(oldseek);
+}
+
+void rewindPackedFile(PackedFile * pf)
+{
+ seekPackedFile(pf, 0, SEEK_SET);
+}
+
+int readPackedFile(PackedFile * pf, void * data, int size)
+{
+ if ((pf != NULL) && (size >= 0) && (data != NULL)) {
+ if (size + pf->seek > pf->size) {
+ size = pf->size - pf->seek;
+ }
+
+ if (size > 0) {
+ memcpy(data, ((char *) pf->data) + pf->seek, size);
+ } else {
+ size = 0;
+ }
+
+ pf->seek += size;
+ } else {
+ size = -1;
+ }
+
+ return(size);
+}
+
+int countPackedFiles()
+{
+ int count = 0;
+ Image *ima;
+ VFont *vf;
+ bSample *sample;
+
+ // let's check if there are packed files...
+ ima = G.main->image.first;
+ while (ima) {
+ if (ima->packedfile) {
+ count++;
+ }
+ ima= ima->id.next;
+ }
+
+ vf = G.main->vfont.first;
+ while (vf) {
+ if (vf->packedfile) {
+ count++;
+ }
+ vf = vf->id.next;
+ }
+
+ sample = samples->first;
+ while (sample) {
+ if (sample->packedfile) {
+ count++;
+ }
+ sample = sample->id.next;
+ }
+
+ return(count);
+}
+
+void freePackedFile(PackedFile * pf)
+{
+ if (pf) {
+ MEM_freeN(pf->data);
+ MEM_freeN(pf);
+ } else {
+ printf("freePackedFile: Trying to free a NULL pointer\n");
+ }
+}
+
+PackedFile * newPackedFileMemory(void *mem, int memlen)
+{
+ PackedFile * pf = MEM_callocN(sizeof(*pf), "PackedFile");
+ pf->data = mem;
+ pf->size = memlen;
+
+ return pf;
+}
+
+PackedFile * newPackedFile(char * filename)
+{
+ PackedFile * pf = NULL;
+ int file, filelen;
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+ void * data;
+
+ waitcursor(1);
+
+ // convert relative filenames to absolute filenames
+
+ strcpy(name, filename);
+ BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
+
+ // open the file
+ // and create a PackedFile structure
+
+ file= open(name, O_BINARY|O_RDONLY);
+ if (file <= 0) {
+ // error("Can't open file: %s", name);
+ } else {
+ filelen = BLI_filesize(file);
+
+ if (filelen == 0) {
+ // MEM_mallocN complains about MEM_mallocN(0, "bla");
+ // we don't care....
+ data = MEM_mallocN(1, "packFile");
+ } else {
+ data = MEM_mallocN(filelen, "packFile");
+ }
+ if (read(file, data, filelen) == filelen) {
+ pf = newPackedFileMemory(data, filelen);
+ }
+
+ close(file);
+ }
+
+ waitcursor(0);
+
+ return (pf);
+}
+
+void packAll()
+{
+ Image *ima;
+ VFont *vf;
+ bSample *sample;
+
+ ima = G.main->image.first;
+ while (ima) {
+ if (ima->packedfile == NULL) {
+ ima->packedfile = newPackedFile(ima->name);
+ }
+ ima= ima->id.next;
+ }
+
+ vf = G.main->vfont.first;
+ while (vf) {
+ if (vf->packedfile == NULL) {
+ vf->packedfile = newPackedFile(vf->name);
+ }
+ vf = vf->id.next;
+ }
+
+
+ sample = samples->first;
+ while (sample) {
+ if (sample->packedfile == NULL) {
+ sound_set_packedfile(sample, newPackedFile(sample->name));
+ }
+ sample = sample->id.next;
+ }
+}
+
+
+/*
+
+// attempt to create a function that generates an unique filename
+// this will work when all funtions in fileops.c understand relative filenames...
+
+char * find_new_name(char * name)
+{
+ char tempname[FILE_MAXDIR + FILE_MAXFILE];
+ char * newname;
+
+ if (fop_exists(name)) {
+ for (number = 1; number <= 999; number++) {
+ sprintf(tempname, "%s.%03d", name, number);
+ if (! fop_exists(tempname)) {
+ break;
+ }
+ }
+ }
+
+ newname = mallocN(strlen(tempname) + 1, "find_new_name");
+ strcpy(newname, tempname);
+
+ return(newname);
+}
+
+*/
+
+int writePackedFile(char * filename, PackedFile *pf)
+{
+ int file, number, remove_tmp = FALSE;
+ int ret_value = RET_OK;
+ char name[FILE_MAXDIR + FILE_MAXFILE];
+ char tempname[FILE_MAXDIR + FILE_MAXFILE];
+/* void * data; */
+
+ waitcursor(1);
+
+ strcpy(name, filename);
+ BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
+
+ if (BLI_exists(name)) {
+ for (number = 1; number <= 999; number++) {
+ sprintf(tempname, "%s.%03d_", name, number);
+ if (! BLI_exists(tempname)) {
+ if (BLI_copy_fileops(name, tempname) == RET_OK) {
+ remove_tmp = TRUE;
+ }
+ break;
+ }
+ }
+ }
+
+ // make sure the path to the file exists...
+ RE_make_existing_file(name);
+
+ file = open(name, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666);
+ if (file >= 0) {
+ if (write(file, pf->data, pf->size) != pf->size) {
+ error("Error writing file: %s", name);
+ ret_value = RET_ERROR;
+ }
+ close(file);
+ } else {
+ error("Error creating file: %s", name);
+ ret_value = RET_ERROR;
+ }
+
+ if (remove_tmp) {
+ if (ret_value == RET_ERROR) {
+ if (BLI_rename(tempname, name) == RET_ERROR) {
+ error("Error restoring tempfile. Check files: '%s' '%s'", tempname, name);
+ }
+ } else {
+ if (BLI_delete(tempname, 0, 0) == RET_ERROR) {
+ error("Error deleting '%s' (ignored)");
+ }
+ }
+ }
+
+ waitcursor(0);
+
+ return (ret_value);
+}
+
+/*
+
+This function compares a packed file to a 'real' file.
+It returns an integer indicating if:
+
+PF_EQUAL - the packed file and original file are identical
+PF_DIFFERENT - the packed file and original file differ
+PF_NOFILE - the original file doens't exist
+
+*/
+
+int checkPackedFile(char * filename, PackedFile * pf)
+{
+ struct stat st;
+ int ret_val, i, len, file;
+ char buf[4096];
+ char name[FILE_MAXDIR + FILE_MAXFILE];
+
+ strcpy(name, filename);
+ BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
+
+ if (stat(name, &st)) {
+ ret_val = PF_NOFILE;
+ } else if (st.st_size != pf->size) {
+ ret_val = PF_DIFFERS;
+ } else {
+ // we'll have to compare the two...
+
+ file = open(name, O_BINARY | O_RDONLY);
+ if (file < 0) {
+ ret_val = PF_NOFILE;
+ } else {
+ ret_val = PF_EQUAL;
+
+ for (i = 0; i < pf->size; i += sizeof(buf)) {
+ len = pf->size - i;
+ if (len > sizeof(buf)) {
+ len = sizeof(buf);
+ }
+
+ if (read(file, buf, len) != len) {
+ // read error ...
+ ret_val = PF_DIFFERS;
+ break;
+ } else {
+ if (memcmp(buf, ((char *)pf->data) + i, len)) {
+ ret_val = PF_DIFFERS;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return(ret_val);
+}
+
+/*
+
+unpackFile() looks at the existing files (abs_name, local_name) and a packed file.
+If how == PF_ASK it offers the user a couple of options what to do with the packed file.
+
+It returns a char * to the existing file name / new file name or NULL when
+there was an error or when the user desides to cancel the operation.
+
+*/
+
+char * unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how)
+{
+ char menu[6 * (FILE_MAXDIR + FILE_MAXFILE + 100)];
+ char line[FILE_MAXDIR + FILE_MAXFILE + 100];
+ char * newname = NULL, * temp = NULL;
+
+ // char newabs[FILE_MAXDIR + FILE_MAXFILE];
+ // char newlocal[FILE_MAXDIR + FILE_MAXFILE];
+
+ if (pf != NULL) {
+ if (how == PF_ASK) {
+ strcpy(menu, "UnPack file%t");
+
+ if (strcmp(abs_name, local_name)) {
+ switch (checkPackedFile(local_name, pf)) {
+ case PF_NOFILE:
+ sprintf(line, "|Create %s%%x%d", local_name, PF_WRITE_LOCAL);
+ strcat(menu, line);
+ break;
+ case PF_EQUAL:
+ sprintf(line, "|Use %s (identical)%%x%d", local_name, PF_USE_LOCAL);
+ strcat(menu, line);
+ break;
+ case PF_DIFFERS:
+ sprintf(line, "|Use %s (differs)%%x%d", local_name, PF_USE_LOCAL);
+ strcat(menu, line);
+ sprintf(line, "|Overwrite %s%%x%d", local_name, PF_WRITE_LOCAL);
+ strcat(menu, line);
+ break;
+ }
+ // sprintf(line, "|%%x%d", PF_INVALID);
+ // strcat(menu, line);
+ }
+
+ switch (checkPackedFile(abs_name, pf)) {
+ case PF_NOFILE:
+ sprintf(line, "|Create %s%%x%d", abs_name, PF_WRITE_ORIGINAL);
+ strcat(menu, line);
+ break;
+ case PF_EQUAL:
+ sprintf(line, "|Use %s (identical)%%x%d", abs_name, PF_USE_ORIGINAL);
+ strcat(menu, line);
+ break;
+ case PF_DIFFERS:
+ sprintf(line, "|Use %s (differs)%%x%d", abs_name, PF_USE_ORIGINAL);
+ strcat(menu, line);
+ sprintf(line, "|Overwrite %s%%x%d", abs_name, PF_WRITE_ORIGINAL);
+ strcat(menu, line);
+ break;
+ }
+
+ how = pupmenu(menu);
+ }
+
+ switch (how) {
+ case -1:
+ case PF_KEEP:
+ break;
+ case PF_USE_LOCAL:
+ // if file exists use it
+ if (BLI_exists(local_name)) {
+ temp = local_name;
+ break;
+ }
+ // else fall through and create it
+ case PF_WRITE_LOCAL:
+ if (writePackedFile(local_name, pf) == RET_OK) {
+ temp = local_name;
+ }
+ break;
+ case PF_USE_ORIGINAL:
+ // if file exists use it
+ if (BLI_exists(abs_name)) {
+ temp = abs_name;
+ break;
+ }
+ // else fall through and create it
+ case PF_WRITE_ORIGINAL:
+ if (writePackedFile(abs_name, pf) == RET_OK) {
+ temp = abs_name;
+ }
+ break;
+ default:
+ printf("unpackFile: unknown return_value %d\n", how);
+ break;
+ }
+
+ if (temp) {
+ newname = MEM_mallocN(strlen(temp) + 1, "unpack_file newname");
+ strcpy(newname, temp);
+ }
+ }
+
+ return (newname);
+}
+
+
+int unpackVFont(VFont * vfont, int how)
+{
+ char localname[FILE_MAXDIR + FILE_MAXFILE], fi[FILE_MAXFILE];
+ char * newname;
+ int ret_value = RET_ERROR;
+
+ if (vfont != NULL) {
+ strcpy(localname, vfont->name);
+ BLI_splitdirstring(localname, fi);
+
+ sprintf(localname, "//fonts/%s", fi);
+
+ newname = unpackFile(vfont->name, localname, vfont->packedfile, how);
+ if (newname != NULL) {
+ ret_value = RET_OK;
+ freePackedFile(vfont->packedfile);
+ vfont->packedfile = 0;
+ strcpy(vfont->name, newname);
+ MEM_freeN(newname);
+ }
+ }
+
+ return (ret_value);
+}
+
+/*
+create_local_name() creates a relative (starting with //) name.
+Because it is allowed to have /'s and \'s in blenderobject names
+we have to remove these first.
+*/
+
+
+void create_local_name(char *localname, char *prefix, char *filename)
+{
+ char tempname[FILE_MAXDIR + FILE_MAXFILE];
+ int i, len;
+
+ strcpy(tempname, filename);
+ len = strlen(tempname);
+
+ for (i = 0; i < len ; i++) {
+ switch (tempname[i])
+ {
+ case '/':
+ case '\\':
+ case ' ':
+ tempname[i] = '_';
+ break;
+ }
+ }
+
+ strcpy(localname, prefix);
+ strcat(localname, tempname);
+}
+
+
+int unpackSample(bSample *sample, int how)
+{
+ char localname[FILE_MAXDIR + FILE_MAXFILE];
+ char * newname;
+ int ret_value = RET_ERROR;
+ PackedFile *pf;
+
+ if (sample != NULL) {
+ create_local_name(localname, "//samples/", sample->id.name + 2);
+
+ newname = unpackFile(sample->name, localname, sample->packedfile, how);
+ if (newname != NULL) {
+ strcpy(sample->name, newname);
+ MEM_freeN(newname);
+
+ pf = sample->packedfile;
+ // because samples and sounds can point to the
+ // same packedfile we have to check them all
+ sound_set_packedfile(sample, NULL);
+ freePackedFile(pf);
+
+ ret_value = RET_OK;
+ }
+ }
+
+ return(ret_value);
+}
+
+int unpackImage(Image * ima, int how)
+{
+ char localname[FILE_MAXDIR + FILE_MAXFILE];
+ char * newname;
+ int ret_value = RET_ERROR;
+
+ if (ima != NULL) {
+ create_local_name(localname, "//textures/", ima->id.name + 2);
+
+ newname = unpackFile(ima->name, localname, ima->packedfile, how);
+ if (newname != NULL) {
+ ret_value = RET_OK;
+ freePackedFile(ima->packedfile);
+ ima->packedfile = 0;
+ strcpy(ima->name, newname);
+ MEM_freeN(newname);
+ free_image_buffers(ima);
+ }
+ }
+
+ return(ret_value);
+}
+
+void unpackAll(int how)
+{
+ Image *ima;
+ VFont *vf;
+ bSample *sample;
+
+ ima = G.main->image.first;
+ while (ima) {
+ if (ima->packedfile) {
+ unpackImage(ima, how);
+ }
+ ima= ima->id.next;
+ }
+
+ vf = G.main->vfont.first;
+ while (vf) {
+ if (vf->packedfile) {
+ unpackVFont(vf, how);
+ }
+ vf = vf->id.next;
+ }
+
+ sample = samples->first;
+ while (sample) {
+ if (sample->packedfile) {
+ unpackSample(sample, how);
+ }
+ sample = sample->id.next;
+ }
+}
diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c
new file mode 100644
index 00000000000..d097dba0db0
--- /dev/null
+++ b/source/blender/blenkernel/intern/property.c
@@ -0,0 +1,269 @@
+
+/* property.c june 2000
+ *
+ * ton roosendaal
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_property_types.h"
+#include "DNA_object_types.h"
+#include "DNA_listBase.h"
+
+
+#include "BLI_blenlib.h"
+#include "BKE_bad_level_calls.h"
+#include "BKE_property.h"
+
+void free_property(bProperty *prop)
+{
+
+ if(prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin);
+ MEM_freeN(prop);
+
+}
+
+void free_properties(ListBase *lb)
+{
+ bProperty *prop;
+
+ while( (prop= lb->first) ) {
+ BLI_remlink(lb, prop);
+ free_property(prop);
+ }
+}
+
+bProperty *copy_property(bProperty *prop)
+{
+ bProperty *propn;
+
+ propn= MEM_dupallocN(prop);
+ if(prop->poin && prop->poin != &prop->data) {
+ propn->poin= MEM_dupallocN(prop->poin);
+ }
+ else propn->poin= &propn->data;
+
+ return propn;
+}
+
+void copy_properties(ListBase *lbn, ListBase *lbo)
+{
+ bProperty *prop, *propn;
+
+ lbn->first= lbn->last= 0;
+ prop= lbo->first;
+ while(prop) {
+ propn= copy_property(prop);
+ BLI_addtail(lbn, propn);
+ prop= prop->next;
+ }
+
+
+}
+
+void init_property(bProperty *prop)
+{
+ /* also use when property changes type */
+
+ if(prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin);
+ prop->poin= 0;
+
+ prop->otype= prop->type;
+ prop->data= 0;
+
+ switch(prop->type) {
+ case PROP_BOOL:
+ prop->poin= &prop->data;
+ break;
+ case PROP_INT:
+ prop->poin= &prop->data;
+ break;
+ case PROP_FLOAT:
+ prop->poin= &prop->data;
+ break;
+ case PROP_STRING:
+ prop->poin= MEM_callocN(MAX_PROPSTRING, "property string");
+ break;
+ case PROP_TIME:
+ prop->poin= &prop->data;
+ break;
+ }
+}
+
+
+bProperty *new_property(int type)
+{
+ bProperty *prop;
+
+ prop= MEM_callocN(sizeof(bProperty), "property");
+ prop->type= type;
+
+ init_property(prop);
+
+ strcpy(prop->name, "prop");
+
+ return prop;
+}
+
+bProperty *get_property(Object *ob, char *name)
+{
+ bProperty *prop;
+
+ prop= ob->prop.first;
+ while(prop) {
+ if( strcmp(prop->name, name)==0 ) return prop;
+ prop= prop->next;
+ }
+ return NULL;
+}
+
+/* negative: prop is smaller
+ * positive: prop is larger
+ */
+int compare_property(bProperty *prop, char *str)
+{
+// extern int Gdfra; /* sector.c */
+ float fvalue, ftest;
+
+ switch(prop->type) {
+ case PROP_BOOL:
+ if(strcasecmp(str, "true")==0) {
+ if(prop->data==1) return 0;
+ else return 1;
+ }
+ else if(strcasecmp(str, "false")==0) {
+ if(prop->data==0) return 0;
+ else return 1;
+ }
+ /* no break, do prop_int too! */
+
+ case PROP_INT:
+ return prop->data - atoi(str);
+
+ case PROP_FLOAT:
+ case PROP_TIME:
+ // WARNING: untested for PROP_TIME
+ // function isn't used currently
+ fvalue= *((float *)&prop->data);
+ ftest= (float)atof(str);
+ if( fvalue > ftest) return 1;
+ else if( fvalue < ftest) return -1;
+ return 0;
+
+ case PROP_STRING:
+ return strcmp(prop->poin, str);
+ }
+
+ return 0;
+}
+
+void set_property(bProperty *prop, char *str)
+{
+// extern int Gdfra; /* sector.c */
+
+ switch(prop->type) {
+ case PROP_BOOL:
+ if(strcasecmp(str, "true")==0) prop->data= 1;
+ else if(strcasecmp(str, "false")==0) prop->data= 0;
+ else prop->data= (atoi(str)!=0);
+ break;
+ case PROP_INT:
+ prop->data= atoi(str);
+ break;
+ case PROP_FLOAT:
+ case PROP_TIME:
+ *((float *)&prop->data)= (float)atof(str);
+ break;
+ case PROP_STRING:
+ strcpy(prop->poin, str);
+ break;
+ }
+
+}
+
+void add_property(bProperty *prop, char *str)
+{
+// extern int Gdfra; /* sector.c */
+
+ switch(prop->type) {
+ case PROP_BOOL:
+ case PROP_INT:
+ prop->data+= atoi(str);
+ break;
+ case PROP_FLOAT:
+ case PROP_TIME:
+ *((float *)&prop->data)+= (float)atof(str);
+ break;
+ case PROP_STRING:
+ /* strcpy(prop->poin, str); */
+ break;
+ }
+}
+
+/* reads value of property, sets it in chars in str */
+void set_property_valstr(bProperty *prop, char *str)
+{
+// extern int Gdfra; /* sector.c */
+
+ if(str == NULL) return;
+
+ switch(prop->type) {
+ case PROP_BOOL:
+ case PROP_INT:
+ sprintf(str, "%d", prop->data);
+ break;
+ case PROP_FLOAT:
+ case PROP_TIME:
+ sprintf(str, "%f", *((float *)&prop->data));
+ break;
+ case PROP_STRING:
+ BLI_strncpy(str, prop->poin, MAX_PROPSTRING);
+ break;
+ }
+}
+
+void cp_property(bProperty *prop1, bProperty *prop2)
+{
+ char str[128];
+
+ set_property_valstr(prop2, str);
+
+ set_property(prop1, str);
+}
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
new file mode 100644
index 00000000000..a105b240942
--- /dev/null
+++ b/source/blender/blenkernel/intern/sca.c
@@ -0,0 +1,631 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * these all are linked to objects (listbase)
+ * all data is 'direct data', not Blender lib data.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "MEM_guardedalloc.h"
+
+#include "nla.h" /* For __NLA: Important, do not remove */
+#include "DNA_text_types.h"
+#include "DNA_controller_types.h"
+#include "DNA_sensor_types.h"
+#include "DNA_actuator_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_blenlib.h"
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_blender.h"
+#include "BKE_sca.h"
+
+void free_text_controllers(Text *txt)
+{
+ Object *ob;
+ bController *cont;
+
+ ob= G.main->object.first;
+ while(ob) {
+ cont= ob->controllers.first;
+ while(cont) {
+ if(cont->type==CONT_PYTHON) {
+ bPythonCont *pc;
+
+ pc= cont->data;
+ if(pc->text==txt) pc->text= NULL;
+ }
+ cont= cont->next;
+ }
+ ob= ob->id.next;
+ }
+}
+
+
+/* ******************* SENSORS ************************ */
+
+void free_sensor(bSensor *sens)
+{
+ if(sens->links) MEM_freeN(sens->links);
+ if(sens->data) MEM_freeN(sens->data);
+ MEM_freeN(sens);
+
+}
+
+void free_sensors(ListBase *lb)
+{
+ bSensor *sens;
+
+ while((sens= lb->first)) {
+ BLI_remlink(lb, sens);
+ free_sensor(sens);
+ }
+}
+
+bSensor *copy_sensor(bSensor *sens)
+{
+ bSensor *sensn;
+
+ sensn= MEM_dupallocN(sens);
+ sensn->flag |= SENS_NEW;
+ if(sens->data) {
+ sensn->data= MEM_dupallocN(sens->data);
+ }
+
+ if(sens->links) sensn->links= MEM_dupallocN(sens->links);
+
+ return sensn;
+}
+
+void copy_sensors(ListBase *lbn, ListBase *lbo)
+{
+ bSensor *sens, *sensn;
+
+ lbn->first= lbn->last= 0;
+ sens= lbo->first;
+ while(sens) {
+ sensn= copy_sensor(sens);
+ BLI_addtail(lbn, sensn);
+ sens= sens->next;
+ }
+}
+
+void init_sensor(bSensor *sens)
+{
+ /* also use when sensor changes type */
+ bNearSensor *ns;
+ bMouseSensor *ms;
+
+ if(sens->data) MEM_freeN(sens->data);
+ sens->data= NULL;
+ sens->pulse = 0;
+
+ switch(sens->type) {
+ case SENS_ALWAYS:
+ sens->pulse = 1;
+ break;
+ case SENS_TOUCH:
+ sens->data= MEM_callocN(sizeof(bTouchSensor), "touchsens");
+ break;
+ case SENS_NEAR:
+ ns=sens->data= MEM_callocN(sizeof(bNearSensor), "nearsens");
+ ns->dist= 1.0;
+ ns->resetdist= 2.0;
+ break;
+ case SENS_KEYBOARD:
+ sens->data= MEM_callocN(sizeof(bKeyboardSensor), "keysens");
+ break;
+ case SENS_PROPERTY:
+ sens->data= MEM_callocN(sizeof(bPropertySensor), "propsens");
+ break;
+ case SENS_MOUSE:
+ ms=sens->data= MEM_callocN(sizeof(bMouseSensor), "mousesens");
+ ms->type= LEFTMOUSE;
+ break;
+ case SENS_COLLISION:
+ sens->data= MEM_callocN(sizeof(bCollisionSensor), "colsens");
+ break;
+ case SENS_RADAR:
+ sens->data= MEM_callocN(sizeof(bRadarSensor), "radarsens");
+ break;
+ case SENS_RANDOM:
+ sens->data= MEM_callocN(sizeof(bRandomSensor), "randomsens");
+ break;
+ case SENS_RAY:
+ sens->data= MEM_callocN(sizeof(bRaySensor), "raysens");
+ break;
+ case SENS_MESSAGE:
+ sens->data= MEM_callocN(sizeof(bMessageSensor), "messagesens");
+ break;
+ default:
+ ; /* this is very severe... I cannot make any memory for this */
+ /* logic brick... */
+ }
+}
+
+bSensor *new_sensor(int type)
+{
+ bSensor *sens;
+
+ sens= MEM_callocN(sizeof(bSensor), "Sensor");
+ sens->type= type;
+ sens->flag= SENS_SHOW;
+
+ init_sensor(sens);
+
+ strcpy(sens->name, "sensor");
+ make_unique_prop_names(sens->name);
+
+ return sens;
+}
+
+/* ******************* CONTROLLERS ************************ */
+
+void unlink_controller(bController *cont)
+{
+ bSensor *sens;
+ Object *ob;
+ int a, removed;
+
+ /* check for controller pointers in sensors */
+ ob= G.main->object.first;
+ while(ob) {
+ sens= ob->sensors.first;
+ while(sens) {
+ removed= 0;
+ for(a=0; a<sens->totlinks; a++) {
+ if(removed) (sens->links)[a-1] = (sens->links)[a];
+ else if((sens->links)[a] == cont) removed= 1;
+ }
+ if(removed) {
+ sens->totlinks--;
+
+ if(sens->totlinks==0) {
+ MEM_freeN(sens->links);
+ sens->links= NULL;
+ }
+ }
+ sens= sens->next;
+ }
+ ob= ob->id.next;
+ }
+}
+
+void unlink_controllers(ListBase *lb)
+{
+ bController *cont;
+
+ for (cont= lb->first; cont; cont= cont->next)
+ unlink_controller(cont);
+}
+
+void free_controller(bController *cont)
+{
+ if(cont->links) MEM_freeN(cont->links);
+
+ /* the controller itself */
+ if(cont->data) MEM_freeN(cont->data);
+ MEM_freeN(cont);
+
+}
+
+void free_controllers(ListBase *lb)
+{
+ bController *cont;
+
+ while((cont= lb->first)) {
+ BLI_remlink(lb, cont);
+ if(cont->slinks) MEM_freeN(cont->slinks);
+ free_controller(cont);
+ }
+}
+
+bController *copy_controller(bController *cont)
+{
+ bController *contn;
+
+ cont->mynew=contn= MEM_dupallocN(cont);
+ contn->flag |= CONT_NEW;
+ if(cont->data) {
+ contn->data= MEM_dupallocN(cont->data);
+ }
+
+ if(cont->links) contn->links= MEM_dupallocN(cont->links);
+ contn->slinks= NULL;
+ contn->totslinks= 0;
+
+ return contn;
+}
+
+void copy_controllers(ListBase *lbn, ListBase *lbo)
+{
+ bController *cont, *contn;
+
+ lbn->first= lbn->last= 0;
+ cont= lbo->first;
+ while(cont) {
+ contn= copy_controller(cont);
+ BLI_addtail(lbn, contn);
+ cont= cont->next;
+ }
+}
+
+void init_controller(bController *cont)
+{
+ /* also use when controller changes type, leave actuators... */
+
+ if(cont->data) MEM_freeN(cont->data);
+ cont->data= 0;
+
+ switch(cont->type) {
+ case CONT_EXPRESSION:
+ cont->data= MEM_callocN(sizeof(bExpressionCont), "expcont");
+ break;
+ case CONT_PYTHON:
+ cont->data= MEM_callocN(sizeof(bPythonCont), "pycont");
+ break;
+ }
+}
+
+bController *new_controller(int type)
+{
+ bController *cont;
+
+ cont= MEM_callocN(sizeof(bController), "Controller");
+ cont->type= type;
+ cont->flag= CONT_SHOW;
+
+ init_controller(cont);
+
+ strcpy(cont->name, "cont");
+ make_unique_prop_names(cont->name);
+
+ return cont;
+}
+
+/* ******************* ACTUATORS ************************ */
+
+void unlink_actuator(bActuator *act)
+{
+ bController *cont;
+ Object *ob;
+ int a, removed;
+
+ /* check for actuator pointers in controllers */
+ ob= G.main->object.first;
+ while(ob) {
+ cont= ob->controllers.first;
+ while(cont) {
+ removed= 0;
+ for(a=0; a<cont->totlinks; a++) {
+ if(removed) (cont->links)[a-1] = (cont->links)[a];
+ else if((cont->links)[a] == act) removed= 1;
+ }
+ if(removed) {
+ cont->totlinks--;
+
+ if(cont->totlinks==0) {
+ MEM_freeN(cont->links);
+ cont->links= NULL;
+ }
+ }
+ cont= cont->next;
+ }
+ ob= ob->id.next;
+ }
+}
+
+void unlink_actuators(ListBase *lb)
+{
+ bActuator *act;
+
+ for (act= lb->first; act; act= act->next)
+ unlink_actuator(act);
+}
+
+void free_actuator(bActuator *act)
+{
+ if(act->data) MEM_freeN(act->data);
+ MEM_freeN(act);
+}
+
+void free_actuators(ListBase *lb)
+{
+ bActuator *act;
+
+ while((act= lb->first)) {
+ BLI_remlink(lb, act);
+ free_actuator(act);
+ }
+}
+
+bActuator *copy_actuator(bActuator *act)
+{
+ bActuator *actn;
+
+ act->mynew=actn= MEM_dupallocN(act);
+ actn->flag |= ACT_NEW;
+ if(act->data) {
+ actn->data= MEM_dupallocN(act->data);
+ }
+
+ return actn;
+}
+
+void copy_actuators(ListBase *lbn, ListBase *lbo)
+{
+ bActuator *act, *actn;
+
+ lbn->first= lbn->last= 0;
+ act= lbo->first;
+ while(act) {
+ actn= copy_actuator(act);
+ BLI_addtail(lbn, actn);
+ act= act->next;
+ }
+}
+
+void init_actuator(bActuator *act)
+{
+ /* also use when actuator changes type */
+ bObjectActuator *oa;
+
+ if(act->data) MEM_freeN(act->data);
+ act->data= 0;
+
+ switch(act->type) {
+#ifdef __NLA
+ case ACT_ACTION:
+ act->data= MEM_callocN(sizeof(bActionActuator), "actionact");
+ break;
+#endif
+ case ACT_SOUND:
+ act->data= MEM_callocN(sizeof(bSoundActuator), "soundact");
+ break;
+ case ACT_CD:
+ act->data= MEM_callocN(sizeof(bCDActuator), "cdact");
+ break;
+ case ACT_OBJECT:
+ act->data= MEM_callocN(sizeof(bObjectActuator), "objectact");
+ oa= act->data;
+ oa->flag= 15;
+ break;
+ case ACT_IPO:
+ act->data= MEM_callocN(sizeof(bIpoActuator), "ipoact");
+ break;
+ case ACT_PROPERTY:
+ act->data= MEM_callocN(sizeof(bPropertyActuator), "propact");
+ break;
+ case ACT_CAMERA:
+ act->data= MEM_callocN(sizeof(bCameraActuator), "camact");
+ break;
+ case ACT_EDIT_OBJECT:
+ act->data= MEM_callocN(sizeof(bEditObjectActuator), "editobact");
+ break;
+ case ACT_CONSTRAINT:
+ act->data= MEM_callocN(sizeof(bConstraintActuator), "cons act");
+ break;
+ case ACT_SCENE:
+ act->data= MEM_callocN(sizeof(bSceneActuator), "scene act");
+ break;
+ case ACT_GROUP:
+ act->data= MEM_callocN(sizeof(bGroupActuator), "group act");
+ break;
+ case ACT_RANDOM:
+ act->data= MEM_callocN(sizeof(bRandomActuator), "random act");
+ break;
+ case ACT_MESSAGE:
+ act->data= MEM_callocN(sizeof(bMessageActuator), "message act");
+ break;
+ case ACT_GAME:
+ act->data= MEM_callocN(sizeof(bGameActuator), "game act");
+ break;
+ case ACT_VISIBILITY:
+ act->data= MEM_callocN(sizeof(bVisibilityActuator), "visibility act");
+ break;
+ default:
+ ; /* this is very severe... I cannot make any memory for this */
+ /* logic brick... */
+ }
+}
+
+bActuator *new_actuator(int type)
+{
+ bActuator *act;
+
+ act= MEM_callocN(sizeof(bActuator), "Actuator");
+ act->type= type;
+ act->flag= ACT_SHOW;
+
+ init_actuator(act);
+
+ strcpy(act->name, "act");
+ make_unique_prop_names(act->name);
+
+ return act;
+}
+
+/* ******************** GENERAL ******************* */
+
+void clear_sca_new_poins_ob(Object *ob)
+{
+ bSensor *sens;
+ bController *cont;
+ bActuator *act;
+
+ sens= ob->sensors.first;
+ while(sens) {
+ sens->flag &= ~SENS_NEW;
+ sens= sens->next;
+ }
+ cont= ob->controllers.first;
+ while(cont) {
+ cont->mynew= NULL;
+ cont->flag &= ~CONT_NEW;
+ cont= cont->next;
+ }
+ act= ob->actuators.first;
+ while(act) {
+ act->mynew= NULL;
+ act->flag &= ~ACT_NEW;
+ act= act->next;
+ }
+}
+
+void clear_sca_new_poins()
+{
+ Object *ob;
+
+ ob= G.main->object.first;
+ while(ob) {
+ clear_sca_new_poins_ob(ob);
+ ob= ob->id.next;
+ }
+}
+
+void set_sca_new_poins_ob(Object *ob)
+{
+ bSensor *sens;
+ bController *cont;
+ bActuator *act;
+ int a;
+
+ sens= ob->sensors.first;
+ while(sens) {
+ if(sens->flag & SENS_NEW) {
+ for(a=0; a<sens->totlinks; a++) {
+ if(sens->links[a] && sens->links[a]->mynew)
+ sens->links[a]= sens->links[a]->mynew;
+ }
+ }
+ sens= sens->next;
+ }
+
+ cont= ob->controllers.first;
+ while(cont) {
+ if(cont->flag & CONT_NEW) {
+ for(a=0; a<cont->totlinks; a++) {
+ if( cont->links[a] && cont->links[a]->mynew)
+ cont->links[a]= cont->links[a]->mynew;
+ }
+ }
+ cont= cont->next;
+ }
+
+
+ act= ob->actuators.first;
+ while(act) {
+ if(act->flag & ACT_NEW) {
+ if(act->type==ACT_EDIT_OBJECT) {
+ bEditObjectActuator *eoa= act->data;
+ ID_NEW(eoa->ob);
+ }
+ else if(act->type==ACT_SCENE) {
+ bSceneActuator *sca= act->data;
+ ID_NEW(sca->camera);
+ }
+ else if(act->type==ACT_CAMERA) {
+ bCameraActuator *ca= act->data;
+ ID_NEW(ca->ob);
+ }
+ else if(act->type==ACT_SCENE) {
+ bSceneActuator *sca= act->data;
+ ID_NEW(sca->camera);
+ }
+ }
+ act= act->next;
+ }
+}
+
+
+void set_sca_new_poins()
+{
+ Object *ob;
+
+ ob= G.main->object.first;
+ while(ob) {
+ set_sca_new_poins_ob(ob);
+ ob= ob->id.next;
+ }
+}
+
+void sca_remove_ob_poin(Object *obt, Object *ob)
+{
+ bSensor *sens;
+ bMessageSensor *ms;
+ bActuator *act;
+ bCameraActuator *ca;
+ bSceneActuator *sa;
+ bEditObjectActuator *eoa;
+ bPropertyActuator *pa;
+ bMessageActuator *ma;
+
+ sens= obt->sensors.first;
+ while(sens) {
+ switch(sens->type) {
+ case SENS_MESSAGE:
+ ms= sens->data;
+ if(ms->fromObject==ob) ms->fromObject= NULL;
+ }
+ sens= sens->next;
+ }
+
+ act= obt->actuators.first;
+ while(act) {
+ switch(act->type) {
+ case ACT_CAMERA:
+ ca= act->data;
+ if(ca->ob==ob) ca->ob= NULL;
+ break;
+ case ACT_PROPERTY:
+ pa= act->data;
+ if(pa->ob==ob) pa->ob= NULL;
+ break;
+ case ACT_SCENE:
+ sa= act->data;
+ if(sa->camera==ob) sa->camera= NULL;
+ break;
+ case ACT_EDIT_OBJECT:
+ eoa= act->data;
+ if(eoa->ob==ob) eoa->ob= NULL;
+ break;
+ case ACT_MESSAGE:
+ ma= act->data;
+ if(ma->toObject==ob) ma->toObject= NULL;
+ break;
+
+ }
+ act= act->next;
+ }
+}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
new file mode 100644
index 00000000000..d1da1d4d1b6
--- /dev/null
+++ b/source/blender/blenkernel/intern/scene.c
@@ -0,0 +1,536 @@
+
+/* scene.c MIXED MODEL
+ *
+ * jan 95
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include "BLI_winstuff.h"
+#include <io.h>
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "nla.h" /* for __NLA : IMPORTANT Do not delete me yet! */
+#ifdef __NLA /* for __NLA : IMPORTANT Do not delete me yet! */
+#include "DNA_armature_types.h" /* for __NLA : IMPORTANT Do not delete me yet! */
+#include "BKE_armature.h" /* for __NLA : IMPORTANT Do not delete me yet! */
+#include "BKE_action.h" /* for __NLA : IMPORTANT Do not delete me yet! */
+#endif /* for __NLA : IMPORTANT Do not delete me yet! */
+
+#include "DNA_constraint_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scriptlink_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_group_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_anim.h"
+
+#include "BKE_library.h"
+
+#include "BPY_extern.h"
+#include "BKE_scene.h"
+#include "BKE_world.h"
+#include "BKE_ipo.h"
+#include "BKE_ika.h"
+#include "BKE_key.h"
+
+void free_avicodecdata(AviCodecData *acd)
+{
+ if (acd) {
+ if (acd->lpFormat){
+ MEM_freeN(acd->lpFormat);
+ acd->lpFormat = NULL;
+ acd->cbFormat = 0;
+ }
+ if (acd->lpParms){
+ MEM_freeN(acd->lpParms);
+ acd->lpParms = NULL;
+ acd->cbParms = 0;
+ }
+ }
+}
+
+/* niet scene zelf vrijgeven */
+void free_scene(Scene *sce)
+{
+ Base *base;
+
+ base= sce->base.first;
+ while(base) {
+ base->object->id.us--;
+ base= base->next;
+ }
+ /* pas op: niet objects vrijgeven! */
+
+ BLI_freelistN(&sce->base);
+ free_editing(sce->ed);
+ if(sce->radio) MEM_freeN(sce->radio);
+ if(sce->fcam) MEM_freeN(sce->fcam);
+ sce->radio= 0;
+
+ BPY_free_scriptlink(&sce->scriptlink);
+ if (sce->r.avicodecdata) {
+ free_avicodecdata(sce->r.avicodecdata);
+ MEM_freeN(sce->r.avicodecdata);
+ sce->r.avicodecdata = NULL;
+ }
+}
+
+Scene *add_scene(char *name)
+{
+ Scene *sce;
+
+ sce= alloc_libblock(&G.main->scene, ID_SCE, name);
+ sce->lay= 1;
+
+ sce->r.mode= R_GAMMA;
+ sce->r.cfra= 1;
+ sce->r.sfra= 1;
+ sce->r.efra= 250;
+ sce->r.xsch= 320;
+ sce->r.ysch= 256;
+ sce->r.xasp= 1;
+ sce->r.yasp= 1;
+ sce->r.xparts= 1;
+ sce->r.yparts= 1;
+ sce->r.size= 100;
+ sce->r.planes= 24;
+ sce->r.quality= 90;
+ sce->r.framapto= 100;
+ sce->r.images= 100;
+ sce->r.framelen= 1.0;
+ sce->r.frs_sec= 25;
+
+ sce->r.xplay= 640;
+ sce->r.yplay= 480;
+ sce->r.freqplay= 60;
+ sce->r.depth= 32;
+
+ sce->r.stereomode = 1; // no stereo
+
+ strcpy(sce->r.backbuf, "//backbuf");
+ strcpy(sce->r.pic, U.renderdir);
+ strcpy(sce->r.ftype, "//ftype");
+
+ BLI_init_rctf(&sce->r.safety, 0.1f, 0.9f, 0.1f, 0.9f);
+ sce->r.osa= 8;
+
+ return sce;
+}
+
+int object_in_scene(Object *ob, Scene *sce)
+{
+ Base *base;
+
+ base= sce->base.first;
+ while(base) {
+ if(base->object == ob) return 1;
+ base= base->next;
+ }
+ return 0;
+}
+
+void sort_baselist(Scene *sce)
+{
+ /* alles in volgorde van parent en track */
+ ListBase tempbase, noparentbase, notyetbase;
+ Base *base, *test=NULL;
+ Object *par;
+ int doit, domore= 0, lastdomore=1;
+
+
+ /* volgorde gelijk houden als er niets veranderd is! */
+ /* hier waren problemen met campos array's: volgorde camera's is van belang */
+
+ while(domore!=lastdomore) {
+
+ lastdomore= domore;
+ domore= 0;
+ tempbase.first= tempbase.last= 0;
+ noparentbase.first= noparentbase.last= 0;
+ notyetbase.first= notyetbase.last= 0;
+
+ while( (base= sce->base.first) ) {
+ BLI_remlink(&sce->base, base);
+
+ par= 0;
+ if(base->object->type==OB_IKA) {
+ Ika *ika= base->object->data;
+ par= ika->parent;
+ }
+
+ if(par || base->object->parent || base->object->track) {
+
+ doit= 0;
+ if(base->object->parent) doit++;
+ if(base->object->track) doit++;
+
+ /* Count constraints */
+ {
+ bConstraint *con;
+ for (con = base->object->constraints.first; con; con=con->next){
+ switch (con->type){
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data=con->data;
+ if (data->tar) doit++;
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data=con->data;
+ if (data->tar) doit++;
+ }
+ break;
+ case CONSTRAINT_TYPE_NULL:
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data=con->data;
+ if (data->tar) doit++;
+
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data=con->data;
+ if (data->tar) doit++;
+ }
+ break;
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data=con->data;
+ if (data->tar) doit++;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if(par) doit++;
+
+ test= tempbase.first;
+ while(test) {
+
+ if(test->object==base->object->parent) doit--;
+ if(test->object==base->object->track) doit--;
+ if(test->object==par) doit--;
+
+ /* Decrement constraints */
+ {
+ bConstraint *con;
+ for (con = base->object->constraints.first; con; con=con->next){
+ switch (con->type){
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data=con->data;
+ if (test->object == data->tar && test->object!=base->object) doit--;
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data=con->data;
+ if (test->object == data->tar && test->object!=base->object) doit--;
+ }
+ break;
+ case CONSTRAINT_TYPE_NULL:
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data=con->data;
+ if (test->object == data->tar && test->object!=base->object) doit--;
+
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data=con->data;
+ if (test->object == data->tar && test->object!=base->object) doit--;
+ }
+ break;
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data=con->data;
+ if (test->object == data->tar && test->object!=base->object) doit--;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if(doit==0) break;
+ test= test->next;
+ }
+
+ if(test) BLI_insertlink(&tempbase, test, base);
+ else {
+ BLI_addhead(&tempbase, base);
+ domore++;
+ }
+
+ }
+ else BLI_addtail(&noparentbase, base);
+
+ }
+ sce->base= noparentbase;
+ addlisttolist(&sce->base, &tempbase);
+ addlisttolist(&sce->base, &notyetbase);
+
+ }
+}
+
+
+void set_scene_bg(Scene *sce)
+{
+ Base *base;
+ Object *ob;
+ Group *group;
+ GroupObject *go;
+ int flag;
+
+ G.scene= sce;
+
+ /* objecten deselecteren (voor dataselect) */
+ ob= G.main->object.first;
+ while(ob) {
+ ob->flag &= ~(SELECT|OB_FROMGROUP);
+ ob= ob->id.next;
+ }
+
+ /* group flags again */
+ group= G.main->group.first;
+ while(group) {
+ go= group->gobject.first;
+ while(go) {
+ if(go->ob) go->ob->flag |= OB_FROMGROUP;
+ go= go->next;
+ }
+ group= group->id.next;
+ }
+
+ /* baselijst sorteren */
+ sort_baselist(sce);
+
+ /* layers en flags uit bases naar objecten kopieeren */
+ base= G.scene->base.first;
+ while(base) {
+
+ base->object->lay= base->lay;
+
+ base->flag &= ~OB_FROMGROUP;
+ flag= base->object->flag & OB_FROMGROUP;
+ base->flag |= flag;
+
+ base->object->ctime= -1234567.0; /* forceer ipo */
+ base= base->next;
+ }
+
+ do_all_ipos(); /* layers/materials */
+
+ BPY_do_all_scripts(SCRIPT_FRAMECHANGED);
+ do_all_keys();
+#ifdef __NLA
+ do_all_actions();
+#endif
+ do_all_ikas();
+
+
+}
+
+void set_scene_name(char *name)
+{
+ Scene *sce;
+
+ for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+ if (BLI_streq(name, sce->id.name+2)) {
+ set_scene_bg(sce);
+ return;
+ }
+ }
+
+ error("Can't find scene: %s", name);
+}
+
+/* used by metaballs
+ * doesnt return the original duplicated object, only dupli's
+ */
+int next_object(int val, Base **base, Object **ob)
+{
+ extern ListBase duplilist;
+ static Object *dupob;
+ static int fase;
+ int run_again=1;
+
+ /* init */
+ if(val==0) {
+ fase= F_START;
+ dupob= 0;
+ }
+ else {
+
+ /* run_again is set when a duplilist has been ended */
+ while(run_again) {
+ run_again= 0;
+
+
+
+ /* de eerste base */
+ if(fase==F_START) {
+ *base= G.scene->base.first;
+ if(*base) {
+ *ob= (*base)->object;
+ fase= F_SCENE;
+ }
+ else {
+ /* uitzondering: een lege scene */
+ if(G.scene->set && G.scene->set->base.first) {
+ *base= G.scene->set->base.first;
+ *ob= (*base)->object;
+ fase= F_SET;
+ }
+ }
+ }
+ else {
+ if(*base && fase!=F_DUPLI) {
+ *base= (*base)->next;
+ if(*base) *ob= (*base)->object;
+ else {
+ if(fase==F_SCENE) {
+ /* de scene is klaar, we gaan door met de set */
+ if(G.scene->set && G.scene->set->base.first) {
+ *base= G.scene->set->base.first;
+ *ob= (*base)->object;
+ fase= F_SET;
+ }
+ }
+ }
+ }
+ }
+
+ if(*base == 0) fase= F_START;
+ else {
+ if(fase!=F_DUPLI) {
+ if( (*base)->object->transflag & OB_DUPLI) {
+
+ make_duplilist(G.scene, (*base)->object);
+ dupob= duplilist.first;
+
+ }
+ }
+ /* dupli's afhandelen */
+ if(dupob) {
+
+ *ob= dupob;
+ fase= F_DUPLI;
+
+ dupob= dupob->id.next;
+ }
+ else if(fase==F_DUPLI) {
+ fase= F_SCENE;
+ free_duplilist();
+ run_again= 1;
+ }
+
+ }
+ }
+ }
+
+ return fase;
+}
+
+Object *scene_find_camera(Scene *sc)
+{
+ Base *base;
+
+ for (base= sc->base.first; base; base= base->next)
+ if (base->object->type==OB_CAMERA)
+ return base->object;
+
+ return NULL;
+}
+
+
+Base *scene_add_base(Scene *sce, Object *ob)
+{
+ Base *b= MEM_callocN(sizeof(*b), "scene_add_base");
+ BLI_addhead(&sce->base, b);
+
+ b->object= ob;
+ b->flag= ob->flag;
+ b->lay= ob->lay;
+
+ return b;
+}
+
+void scene_deselect_all(Scene *sce)
+{
+ Base *b;
+
+ for (b= sce->base.first; b; b= b->next) {
+ b->flag&= ~SELECT;
+ b->object->flag= b->flag;
+ }
+}
+
+void scene_select_base(Scene *sce, Base *selbase)
+{
+ scene_deselect_all(sce);
+
+ selbase->flag |= SELECT;
+ selbase->object->flag= selbase->flag;
+
+ sce->basact= selbase;
+}
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
new file mode 100644
index 00000000000..1f04c20cc72
--- /dev/null
+++ b/source/blender/blenkernel/intern/screen.c
@@ -0,0 +1,53 @@
+
+/* screen.c dec/jan 93/94 GRAPHICS
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "DNA_screen_types.h"
+
+#include "BKE_bad_level_calls.h"
+
+#include "BLI_blenlib.h"
+
+/* don't free screen itself */
+void free_screen(bScreen *sc)
+{
+ unlink_screen(sc);
+
+ BLI_freelistN(&sc->vertbase);
+ BLI_freelistN(&sc->edgebase);
+ BLI_freelistN(&sc->areabase);
+}
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
new file mode 100644
index 00000000000..6f8c46bb877
--- /dev/null
+++ b/source/blender/blenkernel/intern/sound.c
@@ -0,0 +1,112 @@
+/**
+ * sound.c (mar-2001 nzc)
+ *
+ * $Id$
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_packedFile_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_sound.h"
+#include "BKE_packedFile.h"
+
+ListBase _samples = {0,0}, *samples = &_samples;
+
+void sound_free_sound(bSound *sound)
+{
+ /* this crashes blender, PLEASE fix! */
+ // still crashes :(
+ //if (sound) {
+ // sound_set_sample(sound, NULL);
+ //}
+
+}
+
+void sound_free_sample(bSample *sample)
+{
+ if (sample) {
+ if (sample->data != &sample->fakedata[0] && sample->data != NULL) {
+ MEM_freeN(sample->data);
+ sample->data = &sample->fakedata[0];
+ }
+
+ if (sample->packedfile) {
+ freePackedFile(sample->packedfile); //FIXME: crashes sometimes
+ sample->packedfile = NULL;
+ }
+
+ if (sample->alindex != SAMPLE_INVALID) {
+// AUD_free_sample(sample->snd_sample);
+ sample->alindex = SAMPLE_INVALID;
+ }
+
+ sample->type = SAMPLE_INVALID;
+ }
+}
+
+
+
+void sound_set_packedfile(bSample *sample, PackedFile *pf)
+{
+ bSound *sound;
+
+ if (sample) {
+ sample->packedfile = pf;
+ sound = G.main->sound.first;
+ while (sound) {
+ if (sound->sample == sample) {
+ sound->newpackedfile = pf;
+ if (pf == NULL) {
+ strcpy(sound->name, sample->name);
+ }
+ }
+ sound = sound->id.next;
+ }
+ }
+}
+
+PackedFile* sound_find_packedfile(bSound *sound)
+{
+ bSound *search;
+ PackedFile *pf = NULL;
+ char soundname[FILE_MAXDIR + FILE_MAXFILE], searchname[FILE_MAXDIR + FILE_MAXFILE];
+
+ // convert sound->name to abolute filename
+ strcpy(soundname, sound->name);
+ BLI_convertstringcode(soundname, G.sce, G.scene->r.cfra);
+
+ search = G.main->sound.first;
+ while (search) {
+ if (search->sample && search->sample->packedfile) {
+ strcpy(searchname, search->sample->name);
+ BLI_convertstringcode(searchname, G.sce, G.scene->r.cfra);
+
+ if (BLI_streq(searchname, soundname)) {
+ pf = search->sample->packedfile;
+ break;
+ }
+ }
+
+ if (search->newpackedfile) {
+ strcpy(searchname, search->name);
+ BLI_convertstringcode(searchname, G.sce, G.scene->r.cfra);
+ if (BLI_streq(searchname, soundname)) {
+ pf = search->newpackedfile;
+ break;
+ }
+ }
+ search = search->id.next;
+ }
+
+ return (pf);
+}
diff --git a/source/blender/blenkernel/intern/subsurf.c b/source/blender/blenkernel/intern/subsurf.c
new file mode 100644
index 00000000000..3f747fb684f
--- /dev/null
+++ b/source/blender/blenkernel/intern/subsurf.c
@@ -0,0 +1,890 @@
+
+/* subsurf.c MIXED MODEL
+ *
+ * jun 2001
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_subsurf.h"
+#include "BKE_displist.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_arithb.h"
+#include "BLI_linklist.h"
+#include "BLI_memarena.h"
+
+/*
+ * TODO
+ *
+ * make uvco's && vcol's properly subdivided
+ * - requires moving uvco and vcol data to vertices
+ * (where it belongs?), or making sharedness explicit
+ * remove/integrate zsl functions
+ * clean up uvco && vcol stuff
+ * add option to update subsurf only after done transverting
+ * decouple display subdivlevel and render subdivlevel
+ * look into waves/particles with subsurfs
+ * groan... make it work with sticky?
+ * U check if storing tfaces (clut, tpage) in a displist is
+ * going to be a mem problem (for example, on duplicate)
+ * U write game blender convert routine
+ * U thorough rendering check + background
+ *
+ */
+
+/****/
+
+static float *Vec2Cpy(float *t, float *a) {
+ t[0]= a[0];
+ t[1]= a[1];
+ return t;
+}
+static float *Vec3Cpy(float *t, float *a) {
+ t[0]= a[0];
+ t[1]= a[1];
+ t[2]= a[2];
+ return t;
+}
+
+static float *Vec2CpyI(float *t, float x, float y) {
+ t[0]= x;
+ t[1]= y;
+ return t;
+}
+static float *Vec3CpyI(float *t, float x, float y, float z) {
+ t[0]= x;
+ t[1]= y;
+ t[2]= z;
+ return t;
+}
+
+static float *Vec2AvgT(float *t, float *a, float *b) {
+ t[0]= (a[0]+b[0])*0.5f;
+ t[1]= (a[1]+b[1])*0.5f;
+ return t;
+}
+static float *Vec3AvgT(float *t, float *a, float *b) {
+ t[0]= (a[0]+b[0])*0.5f;
+ t[1]= (a[1]+b[1])*0.5f;
+ t[2]= (a[2]+b[2])*0.5f;
+ return t;
+}
+
+static float *Vec3AddT(float *t, float *a, float *b) {
+ t[0]= a[0]+b[0];
+ t[1]= a[1]+b[1];
+ t[2]= a[2]+b[2];
+ return t;
+}
+static float *Vec2Add(float *ta, float *b) {
+ ta[0]+= b[0];
+ ta[1]+= b[1];
+ ta[2]+= b[2];
+ return ta;
+}
+
+static float *Vec3MulNT(float *t, float *a, float n) {
+ t[0]= a[0]*n;
+ t[1]= a[1]*n;
+ t[2]= a[2]*n;
+ return t;
+}
+
+static float *Vec3Add(float *ta, float *b) {
+ ta[0]+= b[0];
+ ta[1]+= b[1];
+ ta[2]+= b[2];
+ return ta;
+}
+
+static float *Vec3MulN(float *ta, float n) {
+ ta[0]*= n;
+ ta[1]*= n;
+ ta[2]*= n;
+ return ta;
+}
+
+/****/
+
+typedef struct _HyperVert HyperVert;
+typedef struct _HyperEdge HyperEdge;
+typedef struct _HyperFace HyperFace;
+typedef struct _HyperMesh HyperMesh;
+
+struct _HyperVert {
+ HyperVert *next;
+
+ float co[3];
+
+ HyperVert *nmv;
+ LinkNode *edges, *faces;
+};
+
+struct _HyperEdge {
+ HyperEdge *next;
+
+ HyperVert *v[2];
+ HyperVert *ep;
+
+ LinkNode *faces;
+};
+
+struct _HyperFace {
+ HyperFace *next;
+
+ int nverts;
+ HyperVert **verts;
+ HyperEdge **edges;
+
+ HyperVert *mid;
+
+ unsigned char (*vcol)[4];
+ float (*uvco)[2];
+
+ /* for getting back tface, matnr, etc */
+ union {
+ int ind;
+ EditVlak *ef;
+ } orig;
+};
+
+struct _HyperMesh {
+ HyperVert *verts;
+ HyperEdge *edges;
+ HyperFace *faces;
+ Mesh *orig_me;
+ short hasuvco, hasvcol;
+
+ MemArena *arena;
+};
+
+/***/
+
+static HyperEdge *hypervert_find_edge(HyperVert *v, HyperVert *to) {
+ LinkNode *l;
+
+ for (l= v->edges; l; l= l->next) {
+ HyperEdge *e= l->link;
+
+ if ((e->v[0]==v&&e->v[1]==to) || (e->v[1]==v&&e->v[0]==to))
+ return e;
+ }
+
+ return NULL;
+}
+
+static int hyperedge_is_boundary(HyperEdge *e) {
+ /* len(e->faces) <= 1 */
+ return (!e->faces || !e->faces->next);
+}
+
+static int hypervert_is_boundary(HyperVert *v) {
+ LinkNode *l;
+
+ for (l= v->edges; l; l= l->next)
+ if (hyperedge_is_boundary(l->link))
+ return 1;
+
+ return 0;
+}
+
+static HyperVert *hyperedge_other_vert(HyperEdge *e, HyperVert *a) {
+ return (a==e->v[0])?e->v[1]:e->v[0];
+}
+
+static HyperVert *hypermesh_add_vert(HyperMesh *hme, float *co) {
+ HyperVert *hv= BLI_memarena_alloc(hme->arena, sizeof(*hv));
+
+ hv->nmv= NULL;
+ hv->edges= NULL;
+ hv->faces= NULL;
+
+ Vec3Cpy(hv->co, co);
+
+ hv->next= hme->verts;
+ hme->verts= hv;
+
+ return hv;
+}
+
+static HyperEdge *hypermesh_add_edge(HyperMesh *hme, HyperVert *v1, HyperVert *v2) {
+ HyperEdge *he= BLI_memarena_alloc(hme->arena, sizeof(*he));
+
+ BLI_linklist_prepend_arena(&v1->edges, he, hme->arena);
+ BLI_linklist_prepend_arena(&v2->edges, he, hme->arena);
+
+ he->v[0]= v1;
+ he->v[1]= v2;
+ he->ep= NULL;
+ he->faces= NULL;
+
+ he->next= hme->edges;
+ hme->edges= he;
+
+ return he;
+}
+
+static HyperFace *hypermesh_add_face(HyperMesh *hme, HyperVert **verts, int nverts) {
+ HyperFace *f= BLI_memarena_alloc(hme->arena, sizeof(*f));
+ HyperVert *last;
+ int j;
+
+ f->mid= NULL;
+ f->vcol= NULL;
+ f->uvco= NULL;
+
+ f->nverts= nverts;
+ f->verts= BLI_memarena_alloc(hme->arena, sizeof(*f->verts)*f->nverts);
+ f->edges= BLI_memarena_alloc(hme->arena, sizeof(*f->edges)*f->nverts);
+
+ last= verts[nverts-1];
+ for (j=0; j<nverts; j++) {
+ HyperVert *v= verts[j];
+ HyperEdge *e= hypervert_find_edge(v, last);
+
+ if (!e)
+ e= hypermesh_add_edge(hme, v, last);
+
+ f->verts[j]= v;
+ f->edges[j]= e;
+
+ BLI_linklist_prepend_arena(&v->faces, f, hme->arena);
+ BLI_linklist_prepend_arena(&e->faces, f, hme->arena);
+
+ last= v;
+ }
+
+ f->next= hme->faces;
+ hme->faces= f;
+
+ return f;
+}
+
+static HyperMesh *hypermesh_new(void) {
+ HyperMesh *hme= MEM_mallocN(sizeof(*hme), "hme");
+
+ hme->verts= NULL;
+ hme->edges= NULL;
+ hme->faces= NULL;
+ hme->orig_me= NULL;
+ hme->hasuvco= hme->hasvcol= 0;
+ hme->arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+
+ return hme;
+}
+
+static HyperMesh *hypermesh_from_mesh(Mesh *me, DispList *dlverts) {
+ HyperMesh *hme= hypermesh_new();
+ HyperVert **vert_tbl;
+ MFace *mface= me->mface;
+ int i, j;
+
+ hme->orig_me= me;
+ if (me->tface)
+ hme->hasvcol= hme->hasuvco= 1;
+ else if (me->mcol)
+ hme->hasvcol= 1;
+
+ vert_tbl= MEM_mallocN(sizeof(*vert_tbl)*me->totvert, "vert_tbl");
+
+ for (i= 0; i<me->totvert; i++) {
+ if (dlverts)
+ vert_tbl[i]= hypermesh_add_vert(hme, &dlverts->verts[i*3]);
+ else
+ vert_tbl[i]= hypermesh_add_vert(hme, me->mvert[i].co);
+ }
+
+ for (i=0; i<me->totface; i++) {
+ MFace *mf= &mface[i];
+
+ if (mf->v3) {
+ int nverts= mf->v4?4:3;
+ HyperVert *verts[4];
+ HyperFace *f;
+
+ verts[0]= vert_tbl[mf->v1];
+ verts[1]= vert_tbl[mf->v2];
+ verts[2]= vert_tbl[mf->v3];
+ if (nverts>3)
+ verts[3]= vert_tbl[mf->v4];
+
+ f= hypermesh_add_face(hme, verts, nverts);
+ f->orig.ind= i;
+
+ if (hme->hasuvco) {
+ TFace *tf= &((TFace*) me->tface)[i];
+
+ f->uvco= BLI_memarena_alloc(hme->arena, sizeof(*f->uvco)*nverts);
+ for (j=0; j<nverts; j++)
+ Vec2Cpy(f->uvco[j], tf->uv[j]);
+
+ f->vcol= BLI_memarena_alloc(hme->arena, sizeof(*f->vcol)*nverts);
+ for (j=0; j<nverts; j++)
+ *((unsigned int*) f->vcol[j])= tf->col[j];
+ } else if (hme->hasvcol) {
+ MCol *mcol= &me->mcol[i*4];
+
+ f->vcol= BLI_memarena_alloc(hme->arena, sizeof(*f->vcol)*nverts);
+ for (j=0; j<nverts; j++)
+ *((unsigned int*) f->vcol[j])= *((unsigned int*) &mcol[j]);
+ }
+ } else {
+ hypermesh_add_edge(hme, vert_tbl[mf->v1], vert_tbl[mf->v2]);
+ }
+ }
+
+ MEM_freeN(vert_tbl);
+
+ return hme;
+}
+
+static HyperMesh *hypermesh_from_editmesh(EditVert *everts, EditEdge *eedges, EditVlak *efaces) {
+ HyperMesh *hme= hypermesh_new();
+ EditVert *ev, *prevev;
+ EditEdge *ee;
+ EditVlak *ef;
+
+ /* hack, tuck the new hypervert pointer into
+ * the ev->prev link so we can find it easy,
+ * then restore real prev links later.
+ */
+ for (ev= everts; ev; ev= ev->next)
+ ev->prev= (EditVert*) hypermesh_add_vert(hme, ev->co);
+
+ for (ee= eedges; ee; ee= ee->next)
+ hypermesh_add_edge(hme, (HyperVert*) ee->v1->prev, (HyperVert*) ee->v2->prev);
+
+ for (ef= efaces; ef; ef= ef->next) {
+ int nverts= ef->v4?4:3;
+ HyperVert *verts[4];
+ HyperFace *f;
+
+ verts[0]= (HyperVert*) ef->v1->prev;
+ verts[1]= (HyperVert*) ef->v2->prev;
+ verts[2]= (HyperVert*) ef->v3->prev;
+ if (nverts>3)
+ verts[3]= (HyperVert*) ef->v4->prev;
+
+ f= hypermesh_add_face(hme, verts, nverts);
+ f->orig.ef= ef;
+ }
+
+ /* see hack above, restore the prev links */
+ for (prevev= NULL, ev= everts; ev; prevev= ev, ev= ev->next)
+ ev->prev= prevev;
+
+ return hme;
+}
+
+static void VColAvgT(unsigned char *t, unsigned char *a, unsigned char *b) {
+ t[0]= (a[0]+b[0])>>1;
+ t[1]= (a[1]+b[1])>>1;
+ t[2]= (a[2]+b[2])>>1;
+ t[3]= (a[3]+b[3])>>1;
+}
+
+static void hypermesh_subdivide(HyperMesh *me, HyperMesh *nme) {
+ HyperVert *v;
+ HyperEdge *e;
+ HyperFace *f;
+ LinkNode *link;
+ float co[3];
+ int j, k, count;
+
+ for (f= me->faces; f; f= f->next) {
+ Vec3CpyI(co, 0.0, 0.0, 0.0);
+ for (j=0; j<f->nverts; j++)
+ Vec3Add(co, f->verts[j]->co);
+ Vec3MulN(co, (float)(1.0/f->nverts));
+
+ f->mid= hypermesh_add_vert(nme, co);
+ }
+
+ for (e= me->edges; e; e= e->next) {
+ if (hyperedge_is_boundary(e)) {
+ Vec3AvgT(co, e->v[0]->co, e->v[1]->co);
+ } else {
+ Vec3AddT(co, e->v[0]->co, e->v[1]->co);
+ for (count=2, link= e->faces; link; count++, link= link->next) {
+ f= (HyperFace *) link->link;
+ Vec3Add(co, f->mid->co);
+ }
+ Vec3MulN(co, (float)(1.0/count));
+ }
+
+ e->ep= hypermesh_add_vert(nme, co);
+ }
+
+ for (v= me->verts; v; v= v->next) {
+ float q[3], r[3], s[3];
+
+ if (hypervert_is_boundary(v)) {
+ Vec3CpyI(r, 0.0, 0.0, 0.0);
+
+ for (count= 0, link= v->edges; link; link= link->next) {
+ if (hyperedge_is_boundary(link->link)) {
+ HyperVert *ov= hyperedge_other_vert(link->link, v);
+
+ Vec3Add(r, ov->co);
+ count++;
+ }
+ }
+
+ /* I believe CC give the factors as
+ 3/2k and 1/4k, but that doesn't make
+ sense (to me) as they don't sum to unity...
+ It's rarely important.
+ */
+ Vec3MulNT(s, v->co, 0.75f);
+ Vec3Add(s, Vec3MulN(r, (float)(1.0/(4.0*count))));
+ } else {
+ Vec3Cpy(q, Vec3Cpy(r, Vec3CpyI(s, 0.0f, 0.0f, 0.0f)));
+
+ for (count=0, link= v->faces; link; count++, link= link->next) {
+ f= (HyperFace *) link->link;
+ Vec3Add(q, f->mid->co);
+ }
+ Vec3MulN(q, (float)(1.0/count));
+
+ for (count=0, link= v->edges; link; count++, link= link->next) {
+ e= (HyperEdge *) link->link;
+ Vec3Add(r, hyperedge_other_vert(e, v)->co);
+ }
+ Vec3MulN(r, (float)(1.0/count));
+
+ Vec3MulNT(s, v->co, (float)(count-2));
+
+ Vec3Add(s, q);
+ Vec3Add(s, r);
+ Vec3MulN(s, (float)(1.0/count));
+ }
+
+ v->nmv= hypermesh_add_vert(nme, s);
+ }
+
+ for (e= me->edges; e; e= e->next) {
+ hypermesh_add_edge(nme, e->v[0]->nmv, e->ep);
+ hypermesh_add_edge(nme, e->v[1]->nmv, e->ep);
+ }
+
+ for (f= me->faces; f; f= f->next) {
+ int last= f->nverts-1;
+ unsigned char vcol_mid[4];
+ unsigned char vcol_edge[4][4];
+ float uvco_mid[2];
+ float uvco_edge[4][4];
+
+ if (me->hasvcol) {
+ int t[4]= {0, 0, 0, 0};
+ for (j=0; j<f->nverts; j++) {
+ t[0]+= f->vcol[j][0];
+ t[1]+= f->vcol[j][1];
+ t[2]+= f->vcol[j][2];
+ t[3]+= f->vcol[j][3];
+ }
+ vcol_mid[0]= t[0]/f->nverts;
+ vcol_mid[1]= t[1]/f->nverts;
+ vcol_mid[2]= t[2]/f->nverts;
+ vcol_mid[3]= t[3]/f->nverts;
+
+ for (j=0; j<f->nverts; last= j, j++)
+ VColAvgT(vcol_edge[j], f->vcol[last], f->vcol[j]);
+ last= f->nverts-1;
+ }
+ if (me->hasuvco) {
+ Vec2CpyI(uvco_mid, 0.0, 0.0);
+ for (j=0; j<f->nverts; j++)
+ Vec2Add(uvco_mid, f->uvco[j]);
+ Vec3MulN(uvco_mid, (float)(1.0/f->nverts));
+
+ for (j=0; j<f->nverts; last= j, j++)
+ Vec2AvgT(uvco_edge[j], f->uvco[last], f->uvco[j]);
+ last= f->nverts-1;
+ }
+
+ for (j=0; j<f->nverts; last=j, j++) {
+ HyperVert *nv[4];
+ HyperFace *nf;
+
+ nv[0]= f->verts[last]->nmv;
+ nv[1]= f->edges[j]->ep;
+ nv[2]= f->mid;
+ nv[3]= f->edges[last]->ep;
+
+ nf= hypermesh_add_face(nme, nv, 4);
+ nf->orig= f->orig;
+
+ if (me->hasvcol) {
+ nf->vcol= BLI_memarena_alloc(nme->arena, sizeof(*nf->vcol)*4);
+
+ for (k=0; k<4; k++) {
+ nf->vcol[0][k]= f->vcol[last][k];
+ nf->vcol[1][k]= vcol_edge[j][k];
+ nf->vcol[2][k]= vcol_mid[k];
+ nf->vcol[3][k]= vcol_edge[last][k];
+ }
+ }
+ if (me->hasuvco) {
+ nf->uvco= BLI_memarena_alloc(nme->arena, sizeof(*nf->uvco)*4);
+
+ Vec2Cpy(nf->uvco[0], f->uvco[last]);
+ Vec2Cpy(nf->uvco[1], uvco_edge[j]);
+ Vec2Cpy(nf->uvco[2], uvco_mid);
+ Vec2Cpy(nf->uvco[3], uvco_edge[last]);
+ }
+ }
+ }
+}
+
+static void hypermesh_free(HyperMesh *me) {
+ BLI_memarena_free(me->arena);
+
+ MEM_freeN(me);
+}
+
+/*****/
+
+static void add_mvert_normals_from_mfaces(MVert *mverts, int nmverts, MFaceInt *mfaces, int nmfaces) {
+ float (*tnorms)[3]= MEM_callocN(nmverts*sizeof(*tnorms), "tnorms");
+ int i;
+
+ for (i=0; i<nmfaces; i++) {
+ MFaceInt *mf= &mfaces[i];
+ float f_no[3];
+
+ if (!mf->v3)
+ continue;
+
+ if (mf->v4)
+ CalcNormFloat4(mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, mverts[mf->v4].co, f_no);
+ else
+ CalcNormFloat(mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, f_no);
+
+ Vec3Add(tnorms[mf->v1], f_no);
+ Vec3Add(tnorms[mf->v2], f_no);
+ Vec3Add(tnorms[mf->v3], f_no);
+ if (mf->v4)
+ Vec3Add(tnorms[mf->v4], f_no);
+ }
+ for (i=0; i<nmverts; i++) {
+ MVert *mv= &mverts[i];
+ float *no= tnorms[i];
+
+ Normalise(no);
+ mv->no[0]= (short)(no[0]*32767.0);
+ mv->no[1]= (short)(no[1]*32767.0);
+ mv->no[2]= (short)(no[2]*32767.0);
+ }
+
+ MEM_freeN(tnorms);
+}
+
+static int hypermesh_get_nverts(HyperMesh *hme) {
+ HyperVert *v;
+ int count= 0;
+
+ for (v= hme->verts; v; v= v->next)
+ count++;
+
+ return count;
+}
+
+static int hypermesh_get_nfaces(HyperMesh *hme) {
+ HyperFace *f;
+ int count= 0;
+
+ for (f= hme->faces; f; f= f->next)
+ count++;
+
+ return count;
+}
+
+static int hypermesh_get_nlines(HyperMesh *hme) {
+ HyperEdge *e;
+ int n= 0;
+
+ for (e= hme->edges; e; e= e->next)
+ if (!e->faces)
+ n++;
+
+ return n;
+}
+
+static int editface_is_hidden(EditVlak *ef) {
+ return (ef->v1->h || ef->v2->h || ef->v3->h || (ef->v4 && ef->v4->h));
+}
+
+static int hypermesh_get_nhidden(HyperMesh *hme) {
+ int count= 0;
+
+ /* hme->orig_me==NULL if we are working on an editmesh */
+ if (!hme->orig_me) {
+ HyperFace *f;
+
+ for (f= hme->faces; f; f= f->next)
+ if (editface_is_hidden(f->orig.ef))
+ count++;
+ }
+
+ return count;
+}
+
+static DispList *hypermesh_to_displist(HyperMesh *hme) {
+ int nverts= hypermesh_get_nverts(hme);
+ int nfaces= hypermesh_get_nfaces(hme) + hypermesh_get_nlines(hme) - hypermesh_get_nhidden(hme);
+ DispList *dl= MEM_callocN(sizeof(*dl), "dl");
+ DispListMesh *dlm= MEM_callocN(sizeof(*dlm), "dlmesh");
+ HyperFace *f;
+ HyperVert *v;
+ HyperEdge *e;
+ TFace *tfaces;
+ MFace *mfaces;
+ MFaceInt *mf;
+ int i, j;
+
+ /* hme->orig_me==NULL if we are working on an editmesh */
+ if (hme->orig_me) {
+ tfaces= hme->orig_me->tface;
+ mfaces= hme->orig_me->mface;
+ } else {
+ tfaces= NULL;
+ mfaces= NULL;
+ }
+
+ dl->type= DL_MESH;
+ dl->mesh= dlm;
+
+ dlm->totvert= nverts;
+ dlm->totface= nfaces;
+ dlm->mvert= MEM_mallocN(dlm->totvert*sizeof(*dlm->mvert), "dlm->mvert");
+ dlm->mface= MEM_mallocN(dlm->totface*sizeof(*dlm->mface), "dlm->mface");
+
+ if (hme->hasuvco)
+ dlm->tface= MEM_callocN(dlm->totface*sizeof(*dlm->tface), "dlm->tface");
+ else if (hme->hasvcol)
+ dlm->mcol= MEM_mallocN(dlm->totface*4*sizeof(*dlm->mcol), "dlm->mcol");
+
+ for (i=0, v= hme->verts; i<nverts; i++, v= v->next) {
+ MVert *mv= &dlm->mvert[i];
+ Vec3Cpy(mv->co, v->co);
+ v->nmv= (void*) i;
+ }
+
+ mf= dlm->mface;
+ for (i=0, f= hme->faces; f; i++, f= f->next) {
+ int voff= (((int) f->verts[3]->nmv)==0)?1:0;
+
+ if (!hme->orig_me && editface_is_hidden(f->orig.ef))
+ continue;
+
+ /* compensate for blender's [braindead] way of encoding
+ * nverts by face vertices, if necessary.
+ */
+
+ mf->v1= (int) f->verts[(0+voff)%4]->nmv;
+ mf->v2= (int) f->verts[(1+voff)%4]->nmv;
+ mf->v3= (int) f->verts[(2+voff)%4]->nmv;
+ mf->v4= (int) f->verts[(3+voff)%4]->nmv;
+
+ if (hme->orig_me) {
+ MFace *origmf= &mfaces[f->orig.ind];
+
+ mf->mat_nr= origmf->mat_nr;
+ mf->flag= origmf->flag;
+ mf->puno= 0;
+ mf->edcode= ME_V1V2|ME_V2V3|ME_V3V4|ME_V4V1;
+ } else {
+ EditVlak *origef= f->orig.ef;
+
+ mf->mat_nr= origef->mat_nr;
+ mf->flag= origef->flag;
+ mf->puno= 0;
+ mf->edcode= ME_V1V2|ME_V2V3|ME_V3V4|ME_V4V1;
+ }
+
+ if (hme->hasuvco) {
+ TFace *origtf, *tf= &dlm->tface[i];
+
+ if (hme->orig_me)
+ origtf= &tfaces[f->orig.ind];
+ else
+ origtf= f->orig.ef->tface;
+
+ for (j=0; j<4; j++) {
+ Vec2Cpy(tf->uv[j], f->uvco[(j+voff)%4]);
+ tf->col[j]= *((unsigned int*) f->vcol[(j+voff)%4]);
+ }
+
+ tf->tpage= origtf->tpage;
+ tf->flag= origtf->flag;
+ tf->transp= origtf->transp;
+ tf->mode= origtf->mode;
+ tf->tile= origtf->tile;
+ } else if (hme->hasvcol) {
+ MCol *mcolbase= &dlm->mcol[i*4];
+
+ for (j=0; j<4; j++)
+ *((unsigned int*) &mcolbase[j])= *((unsigned int*) f->vcol[(j+voff)%4]);
+ }
+
+ mf++;
+ }
+
+ for (e= hme->edges; e; e= e->next) {
+ if (!e->faces) {
+ mf->v1= (int) e->v[0]->nmv;
+ mf->v2= (int) e->v[1]->nmv;
+ mf->v3= 0;
+ mf->v4= 0;
+
+ mf->mat_nr= 0;
+ mf->flag= 0;
+ mf->puno= 0;
+ mf->edcode= ME_V1V2;
+
+ mf++;
+ }
+ }
+
+ add_mvert_normals_from_mfaces(dlm->mvert, dlm->totvert, dlm->mface, dlm->totface);
+
+ return dl;
+}
+
+static DispList *subsurf_subdivide_to_displist(HyperMesh *hme, short subdiv) {
+ DispList *dl;
+ int i;
+
+ for (i= 0; i<subdiv; i++) {
+ HyperMesh *tmp= hypermesh_new();
+ tmp->hasvcol= hme->hasvcol;
+ tmp->hasuvco= hme->hasuvco;
+ tmp->orig_me= hme->orig_me;
+
+ hypermesh_subdivide(hme, tmp);
+ hypermesh_free(hme);
+
+ hme= tmp;
+ }
+
+ dl= hypermesh_to_displist(hme);
+ hypermesh_free(hme);
+
+ return dl;
+}
+
+void subsurf_make_editmesh(Object *ob) {
+ if (G.eded.first) {
+ Mesh *me= ob->data;
+ HyperMesh *hme= hypermesh_from_editmesh(G.edve.first, G.eded.first, G.edvl.first);
+
+ free_displist_by_type(&me->disp, DL_MESH);
+ BLI_addtail(&me->disp, subsurf_subdivide_to_displist(hme, me->subdiv));
+ }
+}
+
+void subsurf_make_mesh(Object *ob, short subdiv) {
+ Mesh *me= ob->data;
+
+ if (me->totface) {
+ HyperMesh *hme= hypermesh_from_mesh(me, find_displist(&ob->disp, DL_VERTS));
+
+ free_displist_by_type(&me->disp, DL_MESH);
+ BLI_addtail(&me->disp, subsurf_subdivide_to_displist(hme, subdiv));
+ }
+}
+
+void subsurf_to_mesh(Object *oldob, Mesh *me) {
+ Mesh *oldme= oldob->data;
+
+ if (oldme->totface) {
+ HyperMesh *hme= hypermesh_from_mesh(oldme, NULL);
+ DispList *dl= subsurf_subdivide_to_displist(hme, oldme->subdiv);
+ DispListMesh *dlm= dl->mesh;
+ MFace *mfaces;
+ int i;
+
+ if (dlm->totvert>65000)
+ error("Too many vertices");
+ else {
+ me->totface= dlm->totface;
+ me->totvert= dlm->totvert;
+
+ me->mvert= MEM_dupallocN(dlm->mvert);
+ me->mface= mfaces= MEM_mallocN(sizeof(*mfaces)*me->totface, "me->mface");
+ me->tface= MEM_dupallocN(dlm->tface);
+ me->mcol= MEM_dupallocN(dlm->mcol);
+
+ for (i=0; i<me->totface; i++) {
+ MFace *mf= &mfaces[i];
+ MFaceInt *oldmf= &dlm->mface[i];
+
+ mf->v1= oldmf->v1;
+ mf->v2= oldmf->v2;
+ mf->v3= oldmf->v3;
+ mf->v4= oldmf->v4;
+ mf->flag= oldmf->flag;
+ mf->mat_nr= oldmf->mat_nr;
+ mf->puno= 0;
+ mf->edcode= ME_V1V2|ME_V2V3|ME_V3V4|ME_V4V1;
+ }
+ }
+
+ free_disp_elem(dl);
+ }
+}
+
+DispList* subsurf_mesh_to_displist(Mesh *me, DispList *dl, short subdiv)
+{
+ HyperMesh *hme;
+
+ hme= hypermesh_from_mesh(me, dl);
+
+ return subsurf_subdivide_to_displist(hme, subdiv);
+}
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
new file mode 100644
index 00000000000..7f1c6f4935b
--- /dev/null
+++ b/source/blender/blenkernel/intern/text.c
@@ -0,0 +1,1986 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <ctype.h> /* isprint() */
+#include <string.h> /* strstr */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_text_types.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+#include "BKE_text.h"
+#include "BKE_library.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BPY_extern.h" // Blender Python library
+
+/***************/ /*
+
+How Texts should work
+--
+A text should relate to a file as follows -
+(Text *)->name should be the place where the
+ file will or has been saved.
+
+(Text *)->flags has the following bits
+ TXT_ISDIRTY - should always be set if the file in mem. differs from
+ the file on disk, or if there is no file on disk.
+ TXT_ISTMP - should always be set if the (Text *)->name file has not
+ been written before, and attempts to save should result
+ in "Save over?"
+ TXT_ISMEM - should always be set if the Text has not been mapped to
+ a file, in which case (Text *)->name may be NULL or garbage.
+ TXT_ISEXT - should always be set if the Text is not to be written into
+ the .blend
+ TXT_ISSCRIPT - should be set if the user has designated the text
+ as a script.
+
+->>> see also: /makesdna/DNA_text_types.h
+
+Display
+--
+The st->top determines at what line the top of the text is displayed.
+If the user moves the cursor the st containing that cursor should
+be popped ... other st's retain their own top location.
+
+*/ /***************/
+
+
+/****************/ /*
+ Undo
+
+Undo/Redo works by storing
+events in a queue, and a pointer
+to the current position in the
+queue...
+
+Events are stored using an
+arbitrary op-code system
+to keep track of
+a) the two cursors (normal and selected)
+b) input (visible and control (ie backspace))
+
+input data is stored as its
+ASCII value, the opcodes are
+then selected to not conflict.
+
+opcodes with data in between are
+written at the beginning and end
+of the data to allow undo and redo
+to simply check the code at the current
+undo position
+
+*/ /***************/
+
+/***/
+
+static void txt_pop_first(Text *text);
+static void txt_pop_last(Text *text);
+static void txt_undo_add_op(Text *text, int op);
+static void txt_undo_add_block(Text *text, int op, char *buf);
+static void txt_delete_line(Text *text, TextLine *line);
+
+/***/
+
+static char *txt_cut_buffer= NULL;
+static unsigned char undoing;
+
+/* allow to switch off undoing externally */
+void txt_set_undostate(int u)
+{
+ undoing = u;
+}
+
+int txt_get_undostate(void)
+{
+ return undoing;
+}
+
+void free_text(Text *text)
+{
+ TextLine *tmp;
+
+ for (tmp= text->lines.first; tmp; tmp= tmp->next)
+ MEM_freeN(tmp->line);
+
+ BLI_freelistN(&text->lines);
+
+ if(text->name) MEM_freeN(text->name);
+ MEM_freeN(text->undo_buf);
+}
+
+Text *add_empty_text(void)
+{
+ Text *ta;
+ TextLine *tmp;
+
+ ta= alloc_libblock(&G.main->text, ID_TXT, "Text");
+ ta->id.us= 1;
+
+ ta->name= NULL;
+
+ ta->undo_pos= -1;
+ ta->undo_len= TXT_INIT_UNDO;
+ ta->undo_buf= MEM_mallocN(ta->undo_len, "undo buf");
+
+ ta->nlines=1;
+ ta->flags= TXT_ISDIRTY | TXT_ISTMP | TXT_ISMEM;
+
+ ta->lines.first= ta->lines.last= NULL;
+
+ tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= (char*) MEM_mallocN(1, "textline_string");
+
+ tmp->line[0]=0;
+ tmp->len= 0;
+
+ tmp->next= NULL;
+ tmp->prev= NULL;
+
+ BLI_addhead(&ta->lines, tmp);
+
+ ta->curl= ta->lines.first;
+ ta->curc= 0;
+ ta->sell= ta->lines.first;
+ ta->selc= 0;
+
+ return ta;
+}
+
+// this function removes any control characters from
+// a textline
+
+static void cleanup_textline(TextLine * tl)
+{
+ int i;
+
+ for (i = 0; i < tl->len; i++ ) {
+ if (tl->line[i] < ' ' && tl->line[i] != '\t') {
+ memmove(tl->line + i, tl->line + i + 1, tl->len - i);
+ tl->len--;
+ i--;
+ }
+ }
+}
+
+int reopen_text(Text *text)
+{
+ FILE *fp;
+ int i, llen, len;
+ unsigned char *buffer;
+ TextLine *tmp;
+ char sdir[FILE_MAXDIR];
+ char sfile[FILE_MAXFILE];
+
+ if (!text || !text->name) return 0;
+
+ BLI_split_dirfile(text->name, sdir, sfile);
+
+ fp= fopen(text->name, "r");
+ if(fp==NULL) return 0;
+
+ /* free memory: */
+
+ for (tmp= text->lines.first; tmp; tmp= tmp->next)
+ MEM_freeN(tmp->line);
+
+ BLI_freelistN(&text->lines);
+
+ text->lines.first= text->lines.last= NULL;
+ text->curl= text->sell= NULL;
+
+ /* clear undo buffer */
+ MEM_freeN(text->undo_buf);
+ text->undo_pos= -1;
+ text->undo_len= TXT_INIT_UNDO;
+ text->undo_buf= MEM_mallocN(text->undo_len, "undo buf");
+
+ text->flags= TXT_ISDIRTY | TXT_ISTMP;
+
+ fseek(fp, 0L, SEEK_END);
+ len= ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+
+ text->undo_pos= -1;
+
+ buffer= MEM_mallocN(len, "text_buffer");
+ // under windows fread can return less then len bytes because
+ // of CR stripping
+ len = fread(buffer, 1, len, fp);
+
+ fclose(fp);
+
+ text->nlines=0;
+ i=0;
+ llen=0;
+ for(i=0; i<len; i++) {
+ if (buffer[i]=='\n') {
+ tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
+
+ if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
+ tmp->line[llen]=0;
+ tmp->len= llen;
+
+ cleanup_textline(tmp);
+
+ BLI_addtail(&text->lines, tmp);
+ text->nlines++;
+
+ llen=0;
+ continue;
+ }
+ llen++;
+ }
+
+ if (llen!=0 || text->nlines==0) {
+ tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
+
+ if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
+
+ tmp->line[llen]=0;
+ tmp->len= llen;
+
+ cleanup_textline(tmp);
+
+ BLI_addtail(&text->lines, tmp);
+ text->nlines++;
+ }
+
+ text->curl= text->sell= text->lines.first;
+ text->curc= text->selc= 0;
+
+ MEM_freeN(buffer);
+ return 1;
+}
+
+Text *add_text(char *file)
+{
+ FILE *fp;
+ int i, llen, len;
+ unsigned char *buffer;
+ TextLine *tmp;
+ Text *ta;
+ char sdir[FILE_MAXDIR];
+ char sfile[FILE_MAXFILE];
+
+ BLI_split_dirfile(file, sdir, sfile);
+
+ fp= fopen(file, "r");
+ if(fp==NULL) return NULL;
+
+ ta= alloc_libblock(&G.main->text, ID_TXT, sfile);
+ ta->id.us= 1;
+
+ ta->lines.first= ta->lines.last= NULL;
+ ta->curl= ta->sell= NULL;
+
+/* ta->flags= TXT_ISTMP | TXT_ISEXT; */
+ ta->flags= TXT_ISTMP;
+
+ fseek(fp, 0L, SEEK_END);
+ len= ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+
+ ta->name= MEM_mallocN(strlen(file)+1, "text_name");
+ strcpy(ta->name, file);
+
+ ta->undo_pos= -1;
+ ta->undo_len= TXT_INIT_UNDO;
+ ta->undo_buf= MEM_mallocN(ta->undo_len, "undo buf");
+
+ buffer= MEM_mallocN(len, "text_buffer");
+ // under windows fread can return less then len bytes because
+ // of CR stripping
+ len = fread(buffer, 1, len, fp);
+
+ fclose(fp);
+
+ ta->nlines=0;
+ i=0;
+ llen=0;
+ for(i=0; i<len; i++) {
+ if (buffer[i]=='\n') {
+ tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
+
+ if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
+ tmp->line[llen]=0;
+ tmp->len= llen;
+
+ cleanup_textline(tmp);
+
+ BLI_addtail(&ta->lines, tmp);
+ ta->nlines++;
+
+ llen=0;
+ continue;
+ }
+ llen++;
+ }
+
+ if (llen!=0 || ta->nlines==0) {
+ tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
+
+ if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
+
+ tmp->line[llen]=0;
+ tmp->len= llen;
+
+ cleanup_textline(tmp);
+
+ BLI_addtail(&ta->lines, tmp);
+ ta->nlines++;
+ }
+
+ ta->curl= ta->sell= ta->lines.first;
+ ta->curc= ta->selc= 0;
+
+ MEM_freeN(buffer);
+
+ return ta;
+}
+
+Text *copy_text(Text *ta)
+{
+ Text *tan;
+ TextLine *line, *tmp;
+
+ tan= copy_libblock(ta);
+
+ tan->name= MEM_mallocN(strlen(ta->name)+1, "text_name");
+ strcpy(tan->name, ta->name);
+
+ tan->flags = ta->flags | TXT_ISDIRTY | TXT_ISTMP;
+
+ tan->lines.first= tan->lines.last= NULL;
+ tan->curl= tan->sell= NULL;
+
+ tan->nlines= ta->nlines;
+
+ line= ta->lines.first;
+ /* Walk down, reconstructing */
+ while (line) {
+ tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= MEM_mallocN(line->len+1, "textline_string");
+ strcpy(tmp->line, line->line);
+
+ tmp->len= line->len;
+
+ BLI_addtail(&tan->lines, tmp);
+
+ line= line->next;
+ }
+
+ tan->curl= tan->sell= tan->lines.first;
+ tan->curc= tan->selc= 0;
+
+ return tan;
+}
+
+/*****************************/
+/* Editing utility functions */
+/*****************************/
+
+static void make_new_line (TextLine *line, char *newline)
+{
+ MEM_freeN(line->line);
+
+ line->line= newline;
+ line->len= strlen(newline);
+}
+
+static TextLine *txt_new_line(char *str)
+{
+ TextLine *tmp;
+
+ if(!str) str= "";
+
+ tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= MEM_mallocN(strlen(str)+1, "textline_string");
+ strcpy(tmp->line, str);
+
+ tmp->len= strlen(str);
+ tmp->next= tmp->prev= NULL;
+
+ return tmp;
+}
+
+static TextLine *txt_new_linen(char *str, int n)
+{
+ TextLine *tmp;
+
+ if(!str) str= "";
+
+ tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= MEM_mallocN(n+1, "textline_string");
+ BLI_strncpy(tmp->line, str, n+1);
+
+ tmp->len= strlen(tmp->line);
+ tmp->next= tmp->prev= NULL;
+
+ return tmp;
+}
+
+void txt_clean_text (Text *text)
+{
+ TextLine **top, **bot;
+
+ if (!text) return;
+
+ if (!text->lines.first) {
+ if (text->lines.last) text->lines.first= text->lines.last;
+ else text->lines.first= text->lines.last= txt_new_line(NULL);
+ }
+
+ if (!text->lines.last) text->lines.last= text->lines.first;
+
+ top= (TextLine **) &text->lines.first;
+ bot= (TextLine **) &text->lines.last;
+
+ while ((*top)->prev) *top= (*top)->prev;
+ while ((*bot)->next) *bot= (*bot)->next;
+
+ if(!text->curl) {
+ if(text->sell) text->curl= text->sell;
+ else text->curl= text->lines.first;
+ text->curc= 0;
+ }
+
+ if(!text->sell) {
+ text->sell= text->curl;
+ text->selc= 0;
+ }
+}
+
+int txt_get_span (TextLine *from, TextLine *to)
+{
+ int ret=0;
+ TextLine *tmp= from;
+
+ if (!to || !from) return 0;
+ if (from==to) return 0;
+
+ /* Look forwards */
+ while (tmp) {
+ if (tmp == to) return ret;
+ ret++;
+ tmp= tmp->next;
+ }
+
+ /* Look backwards */
+ if (!tmp) {
+ tmp= from;
+ ret=0;
+ while(tmp) {
+ if (tmp == to) break;
+ ret--;
+ tmp= tmp->prev;
+ }
+ if(!tmp) ret=0;
+ }
+
+ return ret;
+}
+
+static int txt_illegal_char (char c)
+{
+ if (isprint(c) || c=='\t') return 0;
+
+ return 1;
+}
+
+static void txt_make_dirty (Text *text)
+{
+ text->flags |= TXT_ISDIRTY;
+ if (text->compiled) BPY_free_compiled_text(text);
+}
+
+/****************************/
+/* Cursor utility functions */
+/****************************/
+
+static void txt_curs_cur (Text *text, TextLine ***linep, int **charp)
+{
+ *linep= &text->curl; *charp= &text->curc;
+}
+
+static void txt_curs_sel (Text *text, TextLine ***linep, int **charp)
+{
+ *linep= &text->sell; *charp= &text->selc;
+}
+
+static void txt_curs_first (Text *text, TextLine **linep, int *charp)
+{
+ if (text->curl==text->sell) {
+ *linep= text->curl;
+ if (text->curc<text->selc) *charp= text->curc;
+ else *charp= text->selc;
+ } else if (txt_get_span(text->lines.first, text->curl)<txt_get_span(text->lines.first, text->sell)) {
+ *linep= text->curl;
+ *charp= text->curc;
+ } else {
+ *linep= text->sell;
+ *charp= text->selc;
+ }
+}
+
+/****************************/
+/* Cursor movement functions */
+/****************************/
+
+void txt_move_up(Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, old;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
+ if (!*linep) return;
+ old= *charp;
+
+ if((*linep)->prev) {
+ *linep= (*linep)->prev;
+ if (*charp > (*linep)->len) {
+ *charp= (*linep)->len;
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, (*linep)->next), old, txt_get_span(text->lines.first, *linep), (unsigned short) *charp);
+ } else {
+ if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP);
+ }
+ } else {
+ *charp= 0;
+ if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP);
+ }
+
+ if(!sel) txt_pop_sel(text);
+}
+
+void txt_move_down(Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, old;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
+ if (!*linep) return;
+ old= *charp;
+
+ if((*linep)->next) {
+ *linep= (*linep)->next;
+ if (*charp > (*linep)->len) {
+ *charp= (*linep)->len;
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, (*linep)->prev), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+ } else
+ if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN);
+ } else {
+ *charp= (*linep)->len;
+ if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN);
+ }
+
+ if(!sel) txt_pop_sel(text);
+}
+
+void txt_move_left(Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, oundoing= undoing;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
+ if (!*linep) return;
+
+ undoing= 1;
+ if (*charp== 0) {
+ if ((*linep)->prev) {
+ txt_move_up(text, sel);
+ *charp= (*linep)->len;
+ }
+ } else {
+ (*charp)--;
+ }
+ undoing= oundoing;
+ if(!undoing) txt_undo_add_op(text, sel?UNDO_SLEFT:UNDO_CLEFT);
+
+ if(!sel) txt_pop_sel(text);
+}
+
+void txt_move_right(Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, oundoing= undoing;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
+ if (!*linep) return;
+
+ undoing= 1;
+ if (*charp== (*linep)->len) {
+ if ((*linep)->next) {
+ txt_move_down(text, sel);
+ *charp= 0;
+ }
+ } else {
+ (*charp)++;
+ }
+ undoing= oundoing;
+ if(!undoing) txt_undo_add_op(text, sel?UNDO_SRIGHT:UNDO_CRIGHT);
+
+ if(!sel) txt_pop_sel(text);
+}
+
+void txt_move_bol (Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, old;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else txt_curs_cur(text, &linep, &charp);
+ if (!*linep) return;
+ old= *charp;
+
+ *charp= 0;
+
+ if(!sel) txt_pop_sel(text);
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+}
+
+void txt_move_eol (Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, old;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else txt_curs_cur(text, &linep, &charp);
+ if (!*linep) return;
+ old= *charp;
+
+ *charp= (*linep)->len;
+
+ if(!sel) txt_pop_sel(text);
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+}
+
+void txt_move_bof (Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, old;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else txt_curs_cur(text, &linep, &charp);
+ if (!*linep) return;
+ old= *charp;
+
+ *linep= text->lines.first;
+ *charp= 0;
+
+ if(!sel) txt_pop_sel(text);
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+}
+
+void txt_move_eof (Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, old;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else txt_curs_cur(text, &linep, &charp);
+ if (!*linep) return;
+ old= *charp;
+
+ *linep= text->lines.last;
+ *charp= (*linep)->len;
+
+ if(!sel) txt_pop_sel(text);
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+}
+
+void txt_move_toline (Text *text, unsigned int line, short sel)
+{
+ TextLine **linep, *oldl;
+ int *charp, oldc;
+ unsigned int i;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else txt_curs_cur(text, &linep, &charp);
+ if (!*linep) return;
+ oldc= *charp;
+ oldl= *linep;
+
+ *linep= text->lines.first;
+ for (i=0; i<line; i++) {
+ if ((*linep)->next) *linep= (*linep)->next;
+ else break;
+ }
+ *charp= 0;
+
+ if(!sel) txt_pop_sel(text);
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+}
+
+/****************************/
+/* Text selection functions */
+/****************************/
+
+static void txt_curs_swap (Text *text)
+{
+ TextLine *tmpl;
+ int tmpc;
+
+ tmpl= text->curl;
+ text->curl= text->sell;
+ text->sell= tmpl;
+
+ tmpc= text->curc;
+ text->curc= text->selc;
+ text->selc= tmpc;
+
+ if(!undoing) txt_undo_add_op(text, UNDO_SWAP);
+}
+
+static void txt_pop_first (Text *text)
+{
+
+ if (txt_get_span(text->curl, text->sell)<0 ||
+ (text->curl==text->sell && text->curc>text->selc)) {
+ txt_curs_swap(text);
+ }
+
+ if(!undoing) txt_undo_add_toop(text, UNDO_STO,
+ txt_get_span(text->lines.first, text->sell),
+ text->selc,
+ txt_get_span(text->lines.first, text->curl),
+ text->curc);
+
+ txt_pop_sel(text);
+}
+
+static void txt_pop_last (Text *text)
+{
+ if (txt_get_span(text->curl, text->sell)>0 ||
+ (text->curl==text->sell && text->curc<text->selc)) {
+ txt_curs_swap(text);
+ }
+
+ if(!undoing) txt_undo_add_toop(text, UNDO_STO,
+ txt_get_span(text->lines.first, text->sell),
+ text->selc,
+ txt_get_span(text->lines.first, text->curl),
+ text->curc);
+
+ txt_pop_sel(text);
+}
+
+/* never used: CVS 1.19 */
+/* static void txt_pop_selr (Text *text) */
+
+void txt_pop_sel (Text *text)
+{
+ text->sell= text->curl;
+ text->selc= text->curc;
+}
+
+void txt_order_cursors(Text *text)
+{
+ if (!text) return;
+ if (!text->curl) return;
+ if (!text->sell) return;
+
+ /* Flip so text->curl is before text->sell */
+ if (txt_get_span(text->curl, text->sell)<0 ||
+ (text->curl==text->sell && text->curc>text->selc))
+ txt_curs_swap(text);
+}
+
+int txt_has_sel(Text *text)
+{
+ return ((text->curl!=text->sell) || (text->curc!=text->selc));
+}
+
+static void txt_delete_sel (Text *text)
+{
+ TextLine *tmpl;
+ char *buf;
+
+ if (!text) return;
+ if (!text->curl) return;
+ if (!text->sell) return;
+
+ if (!txt_has_sel(text)) return;
+
+ txt_order_cursors(text);
+
+ if(!undoing) {
+ buf= txt_sel_to_buf(text);
+ txt_undo_add_block(text, UNDO_DBLOCK, buf);
+ MEM_freeN(buf);
+ }
+
+ buf= MEM_mallocN(text->curc+(text->sell->len - text->selc)+1, "textline_string");
+
+ strncpy(buf, text->curl->line, text->curc);
+ strcpy(buf+text->curc, text->sell->line + text->selc);
+ buf[text->curc+(text->sell->len - text->selc)]=0;
+
+ make_new_line(text->curl, buf);
+
+ tmpl= text->sell;
+ while (tmpl != text->curl) {
+ tmpl= tmpl->prev;
+ if (!tmpl) break;
+
+ txt_delete_line(text, tmpl->next);
+ }
+
+ text->sell= text->curl;
+ text->selc= text->curc;
+}
+
+void txt_sel_all (Text *text)
+{
+ if (!text) return;
+
+ text->curl= text->lines.first;
+ text->curc= 0;
+
+ text->sell= text->lines.last;
+ text->selc= text->sell->len;
+}
+
+void txt_sel_line (Text *text)
+{
+ if (!text) return;
+ if (!text->curl) return;
+
+ text->curc= 0;
+ text->sell= text->curl;
+ text->selc= text->sell->len;
+}
+
+/***************************/
+/* Cut and paste functions */
+/***************************/
+
+void txt_print_cutbuffer (void)
+{
+ printf ("Cut buffer\n--\n%s\n--\n", txt_cut_buffer);
+}
+
+char *txt_to_buf (Text *text)
+{
+ int length;
+ TextLine *tmp, *linef, *linel;
+ int charf, charl;
+ char *buf;
+
+ if (!text) return NULL;
+ if (!text->curl) return NULL;
+ if (!text->sell) return NULL;
+
+ linef= text->lines.first;
+ charf= 0;
+
+ linel= text->lines.last;
+ charl= linel->len;
+
+ if (linef == text->lines.last) {
+ length= charl-charf;
+
+ buf= MEM_mallocN(length+2, "text buffer");
+
+ BLI_strncpy(buf, linef->line + charf, length+1);
+ buf[length]=0;
+ } else {
+ length= linef->len - charf;
+ length+= charl;
+ length+= 2; /* For the 2 '\n' */
+
+ tmp= linef->next;
+ while (tmp && tmp!= linel) {
+ length+= tmp->len+1;
+ tmp= tmp->next;
+ }
+
+ buf= MEM_mallocN(length+1, "cut buffer");
+
+ strncpy(buf, linef->line + charf, linef->len-charf);
+ length= linef->len - charf;
+
+ buf[length++]='\n';
+
+ tmp= linef->next;
+ while (tmp && tmp!=linel) {
+ strncpy(buf+length, tmp->line, tmp->len);
+ length+= tmp->len;
+
+ buf[length++]='\n';
+
+ tmp= tmp->next;
+ }
+ strncpy(buf+length, linel->line, charl);
+ length+= charl;
+
+ /* python compiler wants an empty end line */
+ buf[length++]='\n';
+ buf[length]=0;
+ }
+
+ return buf;
+}
+
+int txt_find_string(Text *text, char *findstr)
+{
+ TextLine *tl, *startl;
+ char *s= NULL;
+
+ if (!text || !text->curl || !text->sell) return 0;
+
+ txt_order_cursors(text);
+
+ tl= startl= text->sell;
+
+ s= strstr(&tl->line[text->selc], findstr);
+ while (!s) {
+ tl= tl->next;
+ if (!tl)
+ tl= text->lines.first;
+
+ s= strstr(tl->line, findstr);
+ if (tl==startl)
+ break;
+ }
+
+ if (s) {
+ text->curl= text->sell= tl;
+ text->curc= (int) (s-tl->line);
+ text->selc= text->curc + strlen(findstr);
+
+ return 1;
+ } else
+ return 0;
+}
+
+void txt_cut_sel (Text *text)
+{
+ txt_copy_sel(text);
+
+ txt_delete_sel(text);
+}
+
+char *txt_sel_to_buf (Text *text)
+{
+ char *buf;
+ int length=0;
+ TextLine *tmp, *linef, *linel;
+ int charf, charl;
+
+ if (!text) return NULL;
+ if (!text->curl) return NULL;
+ if (!text->sell) return NULL;
+
+ if (text->curl==text->sell) {
+ linef= linel= text->curl;
+
+ if (text->curc < text->selc) {
+ charf= text->curc;
+ charl= text->selc;
+ } else{
+ charf= text->selc;
+ charl= text->curc;
+ }
+ } else if (txt_get_span(text->curl, text->sell)<0) {
+ linef= text->sell;
+ linel= text->curl;
+
+ charf= text->selc;
+ charl= text->curc;
+ } else {
+ linef= text->curl;
+ linel= text->sell;
+
+ charf= text->curc;
+ charl= text->selc;
+ }
+
+ if (linef == linel) {
+ length= charl-charf;
+
+ buf= MEM_mallocN(length+1, "sel buffer");
+
+ BLI_strncpy(buf, linef->line + charf, length+1);
+ } else {
+ length+= linef->len - charf;
+ length+= charl;
+ length++; /* For the '\n' */
+
+ tmp= linef->next;
+ while (tmp && tmp!= linel) {
+ length+= tmp->len+1;
+ tmp= tmp->next;
+ }
+
+ buf= MEM_mallocN(length+1, "sel buffer");
+
+ strncpy(buf, linef->line+ charf, linef->len-charf);
+ length= linef->len-charf;
+
+ buf[length++]='\n';
+
+ tmp= linef->next;
+ while (tmp && tmp!=linel) {
+ strncpy(buf+length, tmp->line, tmp->len);
+ length+= tmp->len;
+
+ buf[length++]='\n';
+
+ tmp= tmp->next;
+ }
+ strncpy(buf+length, linel->line, charl);
+ length+= charl;
+
+ buf[length]=0;
+ }
+
+ return buf;
+}
+
+void txt_copy_sel (Text *text)
+{
+ int length=0;
+ TextLine *tmp, *linef, *linel;
+ int charf, charl;
+
+ if (!text) return;
+ if (!text->curl) return;
+ if (!text->sell) return;
+
+ if (!txt_has_sel(text)) return;
+
+ if (txt_cut_buffer) MEM_freeN(txt_cut_buffer);
+ txt_cut_buffer= NULL;
+
+ if (text->curl==text->sell) {
+ linef= linel= text->curl;
+
+ if (text->curc < text->selc) {
+ charf= text->curc;
+ charl= text->selc;
+ } else{
+ charf= text->selc;
+ charl= text->curc;
+ }
+ } else if (txt_get_span(text->curl, text->sell)<0) {
+ linef= text->sell;
+ linel= text->curl;
+
+ charf= text->selc;
+ charl= text->curc;
+ } else {
+ linef= text->curl;
+ linel= text->sell;
+
+ charf= text->curc;
+ charl= text->selc;
+ }
+
+ if (linef == linel) {
+ length= charl-charf;
+
+ txt_cut_buffer= MEM_mallocN(length+1, "cut buffera");
+
+ BLI_strncpy(txt_cut_buffer, linef->line + charf, length+1);
+ } else {
+ length+= linef->len - charf;
+ length+= charl;
+ length++; /* For the '\n' */
+
+ tmp= linef->next;
+ while (tmp && tmp!= linel) {
+ length+= tmp->len+1;
+ tmp= tmp->next;
+ }
+
+ txt_cut_buffer= MEM_mallocN(length+1, "cut bufferb");
+
+ strncpy(txt_cut_buffer, linef->line+ charf, linef->len-charf);
+ length= linef->len-charf;
+
+ txt_cut_buffer[length++]='\n';
+
+ tmp= linef->next;
+ while (tmp && tmp!=linel) {
+ strncpy(txt_cut_buffer+length, tmp->line, tmp->len);
+ length+= tmp->len;
+
+ txt_cut_buffer[length++]='\n';
+
+ tmp= tmp->next;
+ }
+ strncpy(txt_cut_buffer+length, linel->line, charl);
+ length+= charl;
+
+ txt_cut_buffer[length]=0;
+ }
+}
+
+void txt_insert_buf(Text *text, char *in_buffer)
+{
+ int i=0, l=0, j, u, len;
+ TextLine *add;
+
+ if (!text) return;
+ if (!in_buffer) return;
+
+ txt_delete_sel(text);
+
+ if(!undoing) txt_undo_add_block (text, UNDO_IBLOCK, in_buffer);
+
+ u= undoing;
+ undoing= 1;
+
+ /* Read the first line (or as close as possible */
+ while (in_buffer[i] && in_buffer[i]!='\n') {
+ txt_add_char(text, in_buffer[i]);
+ i++;
+ }
+
+ if (in_buffer[i]=='\n') txt_split_curline(text);
+ else { undoing = u; return; }
+ i++;
+
+ /* Read as many full lines as we can */
+ len= strlen(in_buffer);
+
+ while (i<len) {
+ l=0;
+
+ while (in_buffer[i] && in_buffer[i]!='\n') {
+ i++; l++;
+ }
+
+ if(in_buffer[i]=='\n') {
+ add= txt_new_linen(in_buffer +(i-l), l);
+ BLI_insertlinkbefore(&text->lines, text->curl, add);
+ i++;
+ } else {
+ for (j= i-l; j<i && j<(int)strlen(in_buffer); j++) {
+ txt_add_char(text, in_buffer[j]);
+ }
+ break;
+ }
+ }
+
+ undoing= u;
+}
+
+void txt_free_cut_buffer(void)
+{
+ if (txt_cut_buffer) MEM_freeN(txt_cut_buffer);
+}
+
+void txt_paste(Text *text)
+{
+ txt_insert_buf(text, txt_cut_buffer);
+}
+
+/******************/
+/* Undo functions */
+/******************/
+
+#define MAX_UNDO_TEST(x) \
+ while (text->undo_pos+x >= text->undo_len) { \
+ if(text->undo_len*2 > TXT_MAX_UNDO) { \
+ error("Undo limit reached, buffer cleared\n"); \
+ MEM_freeN(text->undo_buf); \
+ text->undo_len= TXT_INIT_UNDO; \
+ text->undo_buf= MEM_mallocN(text->undo_len, "undo buf"); \
+ text->undo_pos=-1; \
+ return; \
+ } else { \
+ void *tmp= text->undo_buf; \
+ text->undo_buf= MEM_callocN(text->undo_len*2, "undo buf"); \
+ memcpy(text->undo_buf, tmp, text->undo_len); \
+ text->undo_len*=2; \
+ MEM_freeN(tmp); \
+ } \
+ }
+
+static void dump_buffer(Text *text) {
+ int i= 0;
+
+ while (i++<text->undo_pos) printf("%d: %d %c\n", i, text->undo_buf[i], text->undo_buf[i]);
+}
+
+void txt_print_undo(Text *text)
+{
+ int i= 0;
+ int op;
+ char *ops;
+ int linep, charp;
+
+ dump_buffer(text);
+
+ printf ("---< Undo Buffer >---\n");
+
+ printf ("UndoPosition is %d\n", text->undo_pos);
+
+ while (i<=text->undo_pos) {
+ op= text->undo_buf[i];
+
+ if (op==UNDO_CLEFT) {
+ ops= "Cursor left";
+ } else if (op==UNDO_CRIGHT) {
+ ops= "Cursor right";
+ } else if (op==UNDO_CUP) {
+ ops= "Cursor up";
+ } else if (op==UNDO_CDOWN) {
+ ops= "Cursor down";
+ } else if (op==UNDO_SLEFT) {
+ ops= "Selection left";
+ } else if (op==UNDO_SRIGHT) {
+ ops= "Selection right";
+ } else if (op==UNDO_SUP) {
+ ops= "Selection up";
+ } else if (op==UNDO_SDOWN) {
+ ops= "Selection down";
+ } else if (op==UNDO_STO) {
+ ops= "Selection ";
+ } else if (op==UNDO_CTO) {
+ ops= "Cursor ";
+ } else if (op==UNDO_INSERT) {
+ ops= "Insert";
+ } else if (op==UNDO_BS) {
+ ops= "Backspace";
+ } else if (op==UNDO_DEL) {
+ ops= "Delete";
+ } else if (op==UNDO_SWAP) {
+ ops= "Cursor swap";
+ } else if (op==UNDO_DBLOCK) {
+ ops= "Delete text block";
+ } else if (op==UNDO_IBLOCK) {
+ ops= "Insert text block";
+ } else {
+ ops= "Unknown";
+ }
+
+ printf ("Op (%o) at %d = %s", op, i, ops);
+ if (op==UNDO_INSERT || op==UNDO_BS || op==UNDO_DEL) {
+ i++;
+ printf (" - Char is %c", text->undo_buf[i]);
+ i++;
+ } else if (op==UNDO_STO || op==UNDO_CTO) {
+ i++;
+
+ charp= text->undo_buf[i]; i++;
+ charp= charp+(text->undo_buf[i]<<8); i++;
+
+ linep= text->undo_buf[i]; i++;
+ linep= linep+(text->undo_buf[i]<<8); i++;
+ linep= linep+(text->undo_buf[i]<<16); i++;
+ linep= linep+(text->undo_buf[i]<<24); i++;
+
+ printf ("to <%d, %d> ", linep, charp);
+
+ charp= text->undo_buf[i]; i++;
+ charp= charp+(text->undo_buf[i]<<8); i++;
+
+ linep= text->undo_buf[i]; i++;
+ linep= linep+(text->undo_buf[i]<<8); i++;
+ linep= linep+(text->undo_buf[i]<<16); i++;
+ linep= linep+(text->undo_buf[i]<<24); i++;
+
+ printf ("from <%d, %d>", linep, charp);
+ } else if (op==UNDO_DBLOCK || op==UNDO_IBLOCK) {
+ i++;
+
+ linep= text->undo_buf[i]; i++;
+ linep= linep+(text->undo_buf[i]<<8); i++;
+ linep= linep+(text->undo_buf[i]<<16); i++;
+ linep= linep+(text->undo_buf[i]<<24); i++;
+
+ printf (" (length %d) <", linep);
+
+ while (linep>0) {
+ putchar(text->undo_buf[i]);
+ linep--; i++;
+ }
+
+ linep= text->undo_buf[i]; i++;
+ linep= linep+(text->undo_buf[i]<<8); i++;
+ linep= linep+(text->undo_buf[i]<<16); i++;
+ linep= linep+(text->undo_buf[i]<<24); i++;
+ printf ("> (%d)", linep);
+ }
+
+ printf (" %d\n", i);
+ i++;
+ }
+}
+
+static void txt_undo_add_op(Text *text, int op)
+{
+ MAX_UNDO_TEST(2);
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= op;
+ text->undo_buf[text->undo_pos+1]= 0;
+}
+
+static void txt_undo_add_block(Text *text, int op, char *buf)
+{
+ unsigned int length;
+
+ length= strlen(buf);
+
+ MAX_UNDO_TEST(length+11);
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= op;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (length)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (length>>8)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (length>>16)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (length>>24)&0xff;
+
+ text->undo_pos++;
+ strncpy(text->undo_buf+text->undo_pos, buf, length);
+ text->undo_pos+=length;
+
+ text->undo_buf[text->undo_pos]= (length)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (length>>8)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (length>>16)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (length>>24)&0xff;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= op;
+
+ text->undo_buf[text->undo_pos+1]= 0;
+}
+
+void txt_undo_add_toop(Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc)
+{
+ MAX_UNDO_TEST(15);
+
+ if (froml==tol && fromc==toc) return;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= op;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (fromc)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (fromc>>8)&0xff;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (froml)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (froml>>8)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (froml>>16)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (froml>>24)&0xff;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (toc)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (toc>>8)&0xff;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (tol)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (tol>>8)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (tol>>16)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (tol>>24)&0xff;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= op;
+
+ text->undo_buf[text->undo_pos+1]= 0;
+}
+
+static void txt_undo_add_charop(Text *text, int op, char c)
+{
+ MAX_UNDO_TEST(4);
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= op;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= c;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= op;
+ text->undo_buf[text->undo_pos+1]= 0;
+}
+
+void txt_do_undo(Text *text)
+{
+ int op= text->undo_buf[text->undo_pos], i;
+ unsigned int linep;
+ unsigned short charp;
+ TextLine *holdl;
+ int holdc, holdln;
+ char *buf;
+
+ if (text->undo_pos<0) {
+ return;
+ }
+
+ text->undo_pos--;
+
+ undoing= 1;
+
+ switch(op) {
+ case UNDO_CLEFT:
+ txt_move_right(text, 0);
+ break;
+
+ case UNDO_CRIGHT:
+ txt_move_left(text, 0);
+ break;
+
+ case UNDO_CUP:
+ txt_move_down(text, 0);
+ break;
+
+ case UNDO_CDOWN:
+ txt_move_up(text, 0);
+ break;
+
+ case UNDO_SLEFT:
+ txt_move_right(text, 1);
+ break;
+
+ case UNDO_SRIGHT:
+ txt_move_left(text, 1);
+ break;
+
+ case UNDO_SUP:
+ txt_move_down(text, 1);
+ break;
+
+ case UNDO_SDOWN:
+ txt_move_up(text, 1);
+ break;
+
+ case UNDO_CTO:
+ case UNDO_STO:
+ text->undo_pos--;
+ text->undo_pos--;
+ text->undo_pos--;
+ text->undo_pos--;
+
+ text->undo_pos--;
+ text->undo_pos--;
+
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+
+ charp= text->undo_buf[text->undo_pos]; text->undo_pos--;
+ charp= (charp<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+
+ if (op==UNDO_CTO) {
+ txt_move_toline(text, linep, 0);
+ text->curc= charp;
+ txt_pop_sel(text);
+ } else {
+ txt_move_toline(text, linep, 1);
+ text->selc= charp;
+ }
+
+ text->undo_pos--;
+ break;
+
+ case UNDO_INSERT:
+ txt_backspace_char(text);
+ text->undo_pos--;
+ text->undo_pos--;
+ break;
+
+ case UNDO_BS:
+ txt_add_char(text, text->undo_buf[text->undo_pos]);
+ text->undo_pos--;
+ text->undo_pos--;
+ break;
+
+ case UNDO_DEL:
+ txt_add_char(text, text->undo_buf[text->undo_pos]);
+ txt_move_left(text, 0);
+ text->undo_pos--;
+ text->undo_pos--;
+ break;
+
+ case UNDO_SWAP:
+ txt_curs_swap(text);
+ txt_do_undo(text); /* swaps should appear transparent */
+ break;
+
+ case UNDO_DBLOCK:
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+
+ buf= MEM_mallocN(linep+1, "dblock buffer");
+ for (i=0; i < (int)linep; i++){
+ buf[(linep-1)-i]= text->undo_buf[text->undo_pos];
+ text->undo_pos--;
+ }
+ buf[i]= 0;
+
+ txt_curs_first(text, &holdl, &holdc);
+ holdln= txt_get_span(text->lines.first, holdl);
+
+ txt_insert_buf(text, buf);
+ MEM_freeN(buf);
+
+ text->curl= text->lines.first;
+ while (holdln>0) {
+ if(text->curl->next)
+ text->curl= text->curl->next;
+
+ holdln--;
+ }
+ text->curc= holdc;
+
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+
+ text->undo_pos--;
+
+ break;
+
+ case UNDO_IBLOCK:
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+
+ txt_delete_sel(text);
+ while (linep>0) {
+ txt_backspace_char(text);
+ text->undo_pos--;
+ linep--;
+ }
+
+ text->undo_pos--;
+ text->undo_pos--;
+ text->undo_pos--;
+ text->undo_pos--;
+
+ text->undo_pos--;
+
+ break;
+
+ default:
+ error("Undo buffer error - resetting");
+ text->undo_pos= -1;
+
+ break;
+ }
+
+ undoing= 0;
+}
+
+void txt_do_redo(Text *text)
+{
+ char op;
+ unsigned int linep;
+ unsigned short charp;
+ char *buf;
+
+ text->undo_pos++;
+ op= text->undo_buf[text->undo_pos];
+
+ if (!op) {
+ text->undo_pos--;
+ return;
+ }
+
+ undoing= 1;
+
+ switch(op) {
+ case UNDO_CLEFT:
+ txt_move_left(text, 0);
+ break;
+
+ case UNDO_CRIGHT:
+ txt_move_right(text, 0);
+ break;
+
+ case UNDO_CUP:
+ txt_move_up(text, 0);
+ break;
+
+ case UNDO_CDOWN:
+ txt_move_down(text, 0);
+ break;
+
+ case UNDO_SLEFT:
+ txt_move_left(text, 1);
+ break;
+
+ case UNDO_SRIGHT:
+ txt_move_right(text, 1);
+ break;
+
+ case UNDO_SUP:
+ txt_move_up(text, 1);
+ break;
+
+ case UNDO_SDOWN:
+ txt_move_down(text, 1);
+ break;
+
+ case UNDO_INSERT:
+ text->undo_pos++;
+ txt_add_char(text, text->undo_buf[text->undo_pos]);
+ text->undo_pos++;
+ break;
+
+ case UNDO_BS:
+ text->undo_pos++;
+ txt_backspace_char(text);
+ text->undo_pos++;
+ break;
+
+ case UNDO_DEL:
+ text->undo_pos++;
+ txt_delete_char(text);
+ text->undo_pos++;
+ break;
+
+ case UNDO_SWAP:
+ txt_curs_swap(text);
+ txt_do_undo(text); /* swaps should appear transparent a*/
+ break;
+
+ case UNDO_CTO:
+ case UNDO_STO:
+ text->undo_pos++;
+ text->undo_pos++;
+
+ text->undo_pos++;
+ text->undo_pos++;
+ text->undo_pos++;
+ text->undo_pos++;
+
+ text->undo_pos++;
+
+ charp= text->undo_buf[text->undo_pos];
+ text->undo_pos++;
+ charp= charp+(text->undo_buf[text->undo_pos]<<8);
+
+ text->undo_pos++;
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
+
+ if (op==UNDO_CTO) {
+ txt_move_toline(text, linep, 0);
+ text->curc= charp;
+ txt_pop_sel(text);
+ } else {
+ txt_move_toline(text, linep, 1);
+ text->selc= charp;
+ }
+
+ break;
+
+ case UNDO_DBLOCK:
+ text->undo_pos++;
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
+
+ txt_delete_sel(text);
+ text->undo_pos+=linep;
+
+ text->undo_pos++;
+ text->undo_pos++;
+ text->undo_pos++;
+ text->undo_pos++;
+
+ break;
+
+ case UNDO_IBLOCK:
+ text->undo_pos++;
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
+
+ buf= MEM_mallocN(linep+1, "iblock buffer");
+ memcpy (buf, &text->undo_buf[text->undo_pos], linep);
+ text->undo_pos+= linep;
+ buf[linep]= 0;
+
+ txt_insert_buf(text, buf);
+ MEM_freeN(buf);
+
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
+
+ break;
+
+ default:
+ error("Undo buffer error - resetting");
+ text->undo_pos= -1;
+
+ break;
+ }
+
+ undoing= 0;
+}
+
+/**************************/
+/* Line editing functions */
+/**************************/
+
+void txt_split_curline (Text *text) {
+ TextLine *ins;
+ char *left, *right;
+
+ if (!text) return;
+ if (!text->curl) return;
+
+ txt_delete_sel(text);
+
+ /* Make the two half strings */
+
+ left= MEM_mallocN(text->curc+1, "textline_string");
+ if (text->curc) memcpy(left, text->curl->line, text->curc);
+ left[text->curc]=0;
+
+ right= MEM_mallocN(text->curl->len - text->curc+1, "textline_string");
+ if (text->curl->len - text->curc) memcpy(right, text->curl->line+text->curc, text->curl->len-text->curc);
+ right[text->curl->len - text->curc]=0;
+
+ MEM_freeN(text->curl->line);
+
+ /* Make the new TextLine */
+
+ ins= MEM_mallocN(sizeof(TextLine), "textline");
+ ins->line= left;
+ ins->len= text->curc;
+
+ text->curl->line= right;
+ text->curl->len= text->curl->len - text->curc;
+
+ BLI_insertlinkbefore(&text->lines, text->curl, ins);
+
+ text->curc=0;
+
+ txt_make_dirty(text);
+ txt_clean_text(text);
+
+ txt_pop_sel(text);
+ if(!undoing) txt_undo_add_charop(text, UNDO_INSERT, '\n');
+}
+
+static void txt_delete_line (Text *text, TextLine *line)
+{
+ if (!text) return;
+ if (!text->curl) return;
+
+ BLI_remlink (&text->lines, line);
+
+ if (line->line) MEM_freeN(line->line);
+ MEM_freeN(line);
+
+ txt_make_dirty(text);
+ txt_clean_text(text);
+}
+
+static void txt_combine_lines (Text *text, TextLine *linea, TextLine *lineb)
+{
+ char *tmp;
+
+ if (!text) return;
+
+ if(!linea || !lineb) return;
+
+ tmp= MEM_mallocN(linea->len+lineb->len+1, "textline_string");
+
+ strcpy(tmp, linea->line);
+ strcat(tmp, lineb->line);
+
+ make_new_line(linea, tmp);
+
+ txt_delete_line(text, lineb);
+
+ txt_make_dirty(text);
+ txt_clean_text(text);
+}
+
+void txt_delete_char (Text *text)
+{
+ char c='\n';
+
+ if (!text) return;
+ if (!text->curl) return;
+
+ if (txt_has_sel(text)) {
+ txt_delete_sel(text);
+ return;
+ }
+
+ if (text->curc== text->curl->len) { /* Appending two lines */
+ if (text->curl->next) {
+ txt_combine_lines(text, text->curl, text->curl->next);
+ txt_pop_sel(text);
+ }
+ } else { /* Just deleting a char */
+ int i= text->curc;
+
+ c= text->curl->line[i];
+ while(i< text->curl->len) {
+ text->curl->line[i]= text->curl->line[i+1];
+ i++;
+ }
+ text->curl->len--;
+
+ txt_pop_sel(text);
+ }
+
+ txt_make_dirty(text);
+ txt_clean_text(text);
+
+ if(!undoing) txt_undo_add_charop(text, UNDO_DEL, c);
+}
+
+void txt_backspace_char (Text *text) {
+ char c='\n';
+
+ if (!text) return;
+ if (!text->curl) return;
+
+ if (txt_has_sel(text)) {
+ txt_delete_sel(text);
+ return;
+ }
+
+ if (text->curc==0) { /* Appending two lines */
+ if (text->curl->prev) {
+ text->curl= text->curl->prev;
+ text->curc= text->curl->len;
+
+ txt_combine_lines(text, text->curl, text->curl->next);
+ txt_pop_sel(text);
+ }
+ } else { /* Just backspacing a char */
+ int i= text->curc-1;
+
+ c= text->curl->line[i];
+ while(i< text->curl->len) {
+ text->curl->line[i]= text->curl->line[i+1];
+ i++;
+ }
+ text->curl->len--;
+ text->curc--;
+
+ txt_pop_sel(text);
+ }
+
+ txt_make_dirty(text);
+ txt_clean_text(text);
+
+ if(!undoing) txt_undo_add_charop(text, UNDO_BS, c);
+}
+
+int txt_add_char (Text *text, char add) {
+ int len;
+ char *tmp;
+
+ if (!text) return 0;
+ if (!text->curl) return 0;
+
+ if (add=='\n') {
+ txt_split_curline(text);
+ return 1;
+ }
+
+ if(txt_illegal_char(add)) return 0;
+
+ txt_delete_sel(text);
+
+ tmp= MEM_mallocN(text->curl->len+2, "textline_string");
+
+ if(text->curc) memcpy(tmp, text->curl->line, text->curc);
+ tmp[text->curc]= add;
+
+ len= text->curl->len - text->curc;
+ if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len);
+ tmp[text->curl->len+1]=0;
+
+ make_new_line(text->curl, tmp);
+
+ text->curc++;
+
+ txt_pop_sel(text);
+
+ txt_make_dirty(text);
+ txt_clean_text(text);
+
+ if(!undoing) txt_undo_add_charop(text, UNDO_INSERT, add);
+ return 1;
+}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
new file mode 100644
index 00000000000..eed8a39d6ce
--- /dev/null
+++ b/source/blender/blenkernel/intern/texture.c
@@ -0,0 +1,2320 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_dynlib.h"
+
+#include "MTC_matrixops.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "DNA_texture_types.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_image_types.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "BKE_osa_types.h"
+#include "BKE_plugin_types.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BKE_library.h"
+#include "BKE_image.h"
+#include "BKE_texture.h"
+#include "BKE_key.h"
+#include "BKE_ipo.h"
+
+
+/* These vars form the texture channel */
+float Tin, Tr, Tg, Tb, Ta, Txtra;
+extern int Talpha;
+
+
+/* ------------------------------------------------------------------------- */
+
+/* Alle support voor plugin textures: */
+int test_dlerr(const char *name, const char *symbol)
+{
+ char *err;
+
+ err= PIL_dynlib_get_error_as_string(NULL);
+ if(err) {
+ printf("var1: %s, var2: %s, var3: %s\n", name, symbol, err);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void open_plugin_tex(PluginTex *pit)
+{
+ int (*version)(void);
+
+ /* init all the happy variables */
+ pit->doit= 0;
+ pit->pname= 0;
+ pit->stnames= 0;
+ pit->varstr= 0;
+ pit->result= 0;
+ pit->cfra= 0;
+ pit->version= 0;
+
+ /* clear the error list */
+ PIL_dynlib_get_error_as_string(NULL);
+
+ /* no PIL_dynlib_close! multiple opened plugins... */
+ /* if(pit->handle) PIL_dynlib_close(pit->handle); */
+ /* pit->handle= 0; */
+
+ /* open the needed object */
+ pit->handle= PIL_dynlib_open(pit->name);
+ if(test_dlerr(pit->name, pit->name)) return;
+
+ if (pit->handle != 0) {
+ /* find the address of the version function */
+ version= (int (*)(void)) PIL_dynlib_find_symbol(pit->handle, "plugin_tex_getversion");
+ if (test_dlerr(pit->name, "plugin_tex_getversion")) return;
+
+ if (version != 0) {
+ pit->version= version();
+ if (pit->version==2 || pit->version==3) {
+ int (*info_func)(PluginInfo *);
+ PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info");
+
+ info_func= (int (*)(PluginInfo *))PIL_dynlib_find_symbol(pit->handle, "plugin_getinfo");
+ if (!test_dlerr(pit->name, "plugin_getinfo")) {
+
+ info_func(info);
+
+ pit->doit= (int(*)(void)) info->tex_doit;
+ pit->callback= (void(*)(unsigned short)) info->callback;
+ pit->stypes= info->stypes;
+ pit->vars= info->nvars;
+ pit->pname= info->name;
+ pit->stnames= info->snames;
+ pit->varstr= info->varstr;
+ pit->result= info->result;
+ pit->cfra= info->cfra;
+ if (info->init) info->init();
+ }
+ MEM_freeN(info);
+ } else {
+ printf ("Plugin returned unrecognized version number\n");
+ return;
+ }
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+PluginTex *add_plugin_tex(char *str)
+{
+ PluginTex *pit;
+ VarStruct *varstr;
+ int a;
+
+ pit= MEM_callocN(sizeof(PluginTex), "plugintex");
+
+ strcpy(pit->name, str);
+ open_plugin_tex(pit);
+
+ if(pit->doit==0) {
+ if(pit->handle==0) error("no plugin: %s", str);
+ else error("in plugin: %s", str);
+ MEM_freeN(pit);
+ return NULL;
+ }
+
+ varstr= pit->varstr;
+ for(a=0; a<pit->vars; a++, varstr++) {
+ if( (varstr->type & FLO)==FLO)
+ pit->data[a]= varstr->def;
+ else if( (varstr->type & INT)==INT)
+ *((int *)(pit->data+a))= (int) varstr->def;
+ }
+
+ return pit;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void free_plugin_tex(PluginTex *pit)
+{
+ if(pit==0) return;
+
+ /* geen PIL_dynlib_close: dezelfde plugin kan meerdere keren geopend zijn: 1 handle */
+ MEM_freeN(pit);
+}
+
+/* ****************** COLORBAND ******************* */
+
+ColorBand *add_colorband()
+{
+ ColorBand *coba;
+ int a;
+
+ coba= MEM_callocN( sizeof(ColorBand), "colorband");
+
+ coba->data[0].r= 0.0;
+ coba->data[0].g= 0.0;
+ coba->data[0].b= 0.0;
+ coba->data[0].a= 0.0;
+ coba->data[0].pos= 0.0;
+
+ coba->data[1].r= 0.0;
+ coba->data[1].g= 1.0;
+ coba->data[1].b= 1.0;
+ coba->data[1].a= 1.0;
+ coba->data[1].pos= 1.0;
+
+ for(a=2; a<MAXCOLORBAND; a++) {
+ coba->data[a].r= 0.5;
+ coba->data[a].g= 0.5;
+ coba->data[a].b= 0.5;
+ coba->data[a].a= 1.0;
+ coba->data[a].pos= 0.5;
+ }
+
+ coba->tot= 2;
+
+ return coba;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int do_colorband(ColorBand *coba)
+{
+ CBData *cbd1, *cbd2, *cbd0, *cbd3;
+ float fac, mfac, t[4];
+ int a;
+
+ if(coba->tot==0) return 0;
+ Talpha= 1;
+
+ cbd1= coba->data;
+
+ if(Tin <= cbd1->pos) { /* helemaal links */
+ Tr= cbd1->r;
+ Tg= cbd1->g;
+ Tb= cbd1->b;
+ Ta= cbd1->a;
+ }
+ else {
+ /* we zoeken de eerste pos > Tin */
+
+ for(a=0; a<coba->tot; a++, cbd1++) if(cbd1->pos >= Tin) break;
+
+ if(a==coba->tot) { /* helemaal rechts */
+ cbd1--;
+ Tr= cbd1->r;
+ Tg= cbd1->g;
+ Tb= cbd1->b;
+ Ta= cbd1->a;
+ }
+ else {
+ cbd2= cbd1-1;
+ fac= (Tin-cbd1->pos)/(cbd2->pos-cbd1->pos);
+
+ if(coba->ipotype==2) {
+ /* ipo van r naar l: 3 2 1 0 */
+
+ if(a>=coba->tot-1) cbd0= cbd1;
+ else cbd0= cbd1+1;
+ if(a<2) cbd3= cbd2;
+ else cbd3= cbd2-1;
+
+ set_four_ipo(fac, t, KEY_BSPLINE);
+
+ Tr= t[3]*cbd3->r +t[2]*cbd2->r +t[1]*cbd1->r +t[0]*cbd0->r;
+ Tg= t[3]*cbd3->g +t[2]*cbd2->g +t[1]*cbd1->g +t[0]*cbd0->g;
+ Tb= t[3]*cbd3->b +t[2]*cbd2->b +t[1]*cbd1->b +t[0]*cbd0->b;
+ Ta= t[3]*cbd3->a +t[2]*cbd2->a +t[1]*cbd1->a +t[0]*cbd0->a;
+ CLAMP(Tr, 0.0, 1.0);
+ CLAMP(Tg, 0.0, 1.0);
+ CLAMP(Tb, 0.0, 1.0);
+ CLAMP(Ta, 0.0, 1.0);
+ }
+ else {
+
+ if(coba->ipotype==1) { /* EASE */
+ mfac= fac*fac;
+ fac= 3.0f*mfac-2.0f*mfac*fac;
+ }
+ mfac= 1.0f-fac;
+
+ Tr= mfac*cbd1->r + fac*cbd2->r;
+ Tg= mfac*cbd1->g + fac*cbd2->g;
+ Tb= mfac*cbd1->b + fac*cbd2->b;
+ Ta= mfac*cbd1->a + fac*cbd2->a;
+ }
+ }
+ }
+ return 1; /* OK */
+}
+
+/* ******************* TEX ************************ */
+
+void free_texture(Tex *tex)
+{
+ free_plugin_tex(tex->plugin);
+ if(tex->coba) MEM_freeN(tex->coba);
+ if(tex->env) RE_free_envmap(tex->env);
+}
+
+/* ------------------------------------------------------------------------- */
+
+void default_tex(Tex *tex)
+{
+ tex->stype= 0;
+ tex->imaflag= TEX_INTERPOL+TEX_MIPMAP;
+ tex->extend= TEX_REPEAT;
+ tex->cropxmin= tex->cropymin= 0.0;
+ tex->cropxmax= tex->cropymax= 1.0;
+ tex->xrepeat= tex->yrepeat= 1;
+ tex->fie_ima= 2;
+ tex->sfra= 1;
+ tex->frames= 0;
+ tex->offset= 0;
+ tex->noisesize= 0.25;
+ tex->noisedepth= 2;
+ tex->turbul= 5.0;
+ tex->bright= 1.0;
+ tex->contrast= tex->filtersize= 1.0;
+ tex->rfac= 1.0;
+ tex->gfac= 1.0;
+ tex->bfac= 1.0;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+Tex *add_texture(char *name)
+{
+ Tex *tex;
+
+ tex= alloc_libblock(&G.main->tex, ID_TE, name);
+
+ default_tex(tex);
+
+ return tex;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void default_mtex(MTex *mtex)
+{
+ mtex->texco= TEXCO_ORCO;
+ mtex->mapto= MAP_COL;
+ mtex->object= 0;
+ mtex->projx= PROJ_X;
+ mtex->projy= PROJ_Y;
+ mtex->projz= PROJ_Z;
+ mtex->mapping= MTEX_FLAT;
+ mtex->ofs[0]= 0.0;
+ mtex->ofs[1]= 0.0;
+ mtex->ofs[2]= 0.0;
+ mtex->size[0]= 1.0;
+ mtex->size[1]= 1.0;
+ mtex->size[2]= 1.0;
+ mtex->tex= 0;
+ mtex->texflag= 0;
+ mtex->colormodel= 0;
+ mtex->r= 1.0;
+ mtex->g= 0.0;
+ mtex->b= 1.0;
+ mtex->k= 1.0;
+ mtex->def_var= 1.0;
+ mtex->blendtype= MTEX_BLEND;
+ mtex->colfac= 1.0;
+ mtex->norfac= 0.5;
+ mtex->varfac= 1.0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+MTex *add_mtex()
+{
+ MTex *mtex;
+
+ mtex= MEM_callocN(sizeof(MTex), "add_mtex");
+
+ default_mtex(mtex);
+
+ return mtex;
+}
+
+/* ------------------------------------------------------------------------- */
+
+Tex *copy_texture(Tex *tex)
+{
+ Tex *texn;
+
+ texn= copy_libblock(tex);
+ if(texn->type==TEX_IMAGE) id_us_plus((ID *)texn->ima);
+ else texn->ima= 0;
+
+ if(texn->plugin) {
+ texn->plugin= MEM_dupallocN(texn->plugin);
+ open_plugin_tex(texn->plugin);
+ }
+
+ if(texn->coba) texn->coba= MEM_dupallocN(texn->coba);
+ if(texn->env) texn->env= RE_copy_envmap(texn->env);
+
+ return texn;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void make_local_texture(Tex *tex)
+{
+ Tex *texn;
+ Material *ma;
+ World *wrld;
+ Lamp *la;
+ int a, local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(tex->id.lib==0) return;
+
+ /* speciaal geval: ima altijd meteen lokaal */
+ if(tex->ima) {
+ tex->ima->id.lib= 0;
+ tex->ima->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)tex->ima, 0);
+ }
+
+ if(tex->id.us==1) {
+ tex->id.lib= 0;
+ tex->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)tex, 0);
+
+ return;
+ }
+
+ ma= G.main->mat.first;
+ while(ma) {
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a] && ma->mtex[a]->tex==tex) {
+ if(ma->id.lib) lib= 1;
+ else local= 1;
+ }
+ }
+ ma= ma->id.next;
+ }
+ la= G.main->lamp.first;
+ while(la) {
+ for(a=0; a<8; a++) {
+ if(la->mtex[a] && la->mtex[a]->tex==tex) {
+ if(la->id.lib) lib= 1;
+ else local= 1;
+ }
+ }
+ la= la->id.next;
+ }
+ wrld= G.main->world.first;
+ while(wrld) {
+ for(a=0; a<8; a++) {
+ if(wrld->mtex[a] && wrld->mtex[a]->tex==tex) {
+ if(wrld->id.lib) lib= 1;
+ else local= 1;
+ }
+ }
+ wrld= wrld->id.next;
+ }
+
+ if(local && lib==0) {
+ tex->id.lib= 0;
+ tex->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)tex, 0);
+ }
+ else if(local && lib) {
+ texn= copy_texture(tex);
+ texn->id.us= 0;
+
+ ma= G.main->mat.first;
+ while(ma) {
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a] && ma->mtex[a]->tex==tex) {
+ if(ma->id.lib==0) {
+ ma->mtex[a]->tex= texn;
+ texn->id.us++;
+ tex->id.us--;
+ }
+ }
+ }
+ ma= ma->id.next;
+ }
+ la= G.main->lamp.first;
+ while(la) {
+ for(a=0; a<8; a++) {
+ if(la->mtex[a] && la->mtex[a]->tex==tex) {
+ if(la->id.lib==0) {
+ la->mtex[a]->tex= texn;
+ texn->id.us++;
+ tex->id.us--;
+ }
+ }
+ }
+ la= la->id.next;
+ }
+ wrld= G.main->world.first;
+ while(wrld) {
+ for(a=0; a<8; a++) {
+ if(wrld->mtex[a] && wrld->mtex[a]->tex==tex) {
+ if(wrld->id.lib==0) {
+ wrld->mtex[a]->tex= texn;
+ texn->id.us++;
+ tex->id.us--;
+ }
+ }
+ }
+ wrld= wrld->id.next;
+ }
+
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void autotexname(Tex *tex)
+{
+/* extern char texstr[15][8]; *//* buttons.c, already in bad lev calls*/
+ Image *ima;
+ char di[FILE_MAXDIR], fi[FILE_MAXFILE];
+
+ if(tex) {
+ if(tex->type==TEX_IMAGE) {
+ ima= tex->ima;
+ if(ima) {
+ strcpy(di, ima->name);
+ BLI_splitdirstring(di, fi);
+ strcpy(di, "I.");
+ strcat(di, fi);
+ new_id(&G.main->tex, (ID *)tex, di);
+ }
+ else new_id(&G.main->tex, (ID *)tex, texstr[tex->type]);
+ }
+ else if(tex->type==TEX_PLUGIN && tex->plugin) new_id(&G.main->tex, (ID *)tex, tex->plugin->pname);
+ else new_id(&G.main->tex, (ID *)tex, texstr[tex->type]);
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void init_render_texture(Tex *tex)
+{
+ Image *ima;
+ int imanr;
+ unsigned short numlen;
+ char name[256], head[FILE_MAXFILE], tail[FILE_MAXFILE];
+
+ /* is also used as signal */
+ tex->nor= 0;
+
+ /* imap testen */
+ if(tex->frames && tex->ima && tex->ima->name) { /* frames */
+ strcpy(name, tex->ima->name);
+
+ imanr= calcimanr(G.scene->r.cfra, tex);
+
+ if(tex->imaflag & TEX_ANIM5) {
+ if(tex->ima->lastframe != imanr) {
+ if(tex->ima->ibuf) IMB_freeImBuf(tex->ima->ibuf);
+ tex->ima->ibuf= 0;
+ tex->ima->lastframe= imanr;
+ }
+ }
+ else {
+ /* voor patch field-ima rendering */
+ tex->ima->lastframe= imanr;
+
+ BLI_stringdec(name, head, tail, &numlen);
+ BLI_stringenc(name, head, tail, numlen, imanr);
+
+ ima= add_image(name);
+
+ if(ima) {
+ ima->flag |= IMA_FROMANIM;
+
+ if(tex->ima) tex->ima->id.us--;
+ tex->ima= ima;
+
+ ima->ok= 1;
+ }
+ }
+ }
+ if(tex->imaflag & (TEX_ANTIALI+TEX_ANTISCALE)) {
+ if(tex->ima && tex->ima->lastquality<R.osa) {
+ if(tex->ima->ibuf) IMB_freeImBuf(tex->ima->ibuf);
+ tex->ima->ibuf= 0;
+ }
+ }
+
+ if(tex->type==TEX_PLUGIN) {
+ if(tex->plugin && tex->plugin->doit) {
+ if(tex->plugin->cfra) {
+ *(tex->plugin->cfra)= frame_to_float(G.scene->r.cfra);
+ }
+ }
+ }
+ else if(tex->type==TEX_ENVMAP) {
+ /* just in case */
+ tex->imaflag= TEX_INTERPOL | TEX_MIPMAP;
+ tex->extend= TEX_CLIP;
+
+ if(tex->env) {
+ /* temporal solution: layer 21 is to indicate an anvmap object */
+ tex->env->notlay |= (1<<20);
+ if(tex->env->object) tex->env->object->lay |= (1<<20);
+
+ if(R.flag & R_RENDERING) {
+ if(tex->env->stype==ENV_ANIM) RE_free_envmapdata(tex->env);
+ }
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void init_render_textures()
+{
+ Tex *tex;
+
+ tex= G.main->tex.first;
+ while(tex) {
+ if(tex->id.us) init_render_texture(tex);
+ tex= tex->id.next;
+ }
+
+ free_unused_animimages();
+}
+
+/* ------------------------------------------------------------------------- */
+
+void end_render_texture(Tex *tex)
+{
+
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void end_render_textures()
+{
+ Tex *tex;
+
+ tex= G.main->tex.first;
+ while(tex) {
+ if(tex->id.us) end_render_texture(tex);
+ tex= tex->id.next;
+ }
+
+}
+
+
+/* ************************** */
+
+int clouds(Tex *tex, float *texvec)
+{
+ float (*turbfunc)(float, float, float, float, int);
+
+ if(tex->noisetype==TEX_NOISESOFT) turbfunc= BLI_turbulence;
+ else turbfunc= BLI_turbulence1;
+
+ Tin= turbfunc(tex->noisesize, texvec[0], texvec[1], texvec[2], tex->noisedepth);
+
+ if(tex->stype==1) {
+
+ Tr= Tin;
+ Tg= turbfunc(tex->noisesize, texvec[1], texvec[0], texvec[2], tex->noisedepth);
+
+ Tb= turbfunc(tex->noisesize,texvec[1],texvec[2],texvec[0], tex->noisedepth);
+
+ BRICONRGB;
+ Ta= 1.0;
+
+ return 1;
+ }
+
+ BRICON;
+
+ if(tex->flag & TEX_COLORBAND) return do_colorband(tex->coba);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int blend(Tex *tex, float *texvec)
+{
+ float x, y, t;
+
+ if(tex->flag & TEX_FLIPBLEND) {
+ x= texvec[1];
+ y= texvec[0];
+ }
+ else {
+ x= texvec[0];
+ y= texvec[1];
+ }
+
+ if(tex->stype==0) { /* lin */
+ Tin= (1.0+x)/2.0;
+ }
+ else if(tex->stype==1) { /* quad */
+ Tin= (1.0+x)/2.0;
+ if(Tin<0.0) Tin= 0.0;
+ else Tin*= Tin;
+ }
+ else if(tex->stype==2) { /* ease */
+ Tin= (1.0+x)/2.0;
+ if(Tin<=.0) Tin= 0.0;
+ else if(Tin>=1.0) Tin= 1.0;
+ else {
+ t= Tin*Tin;
+ Tin= (3.0*t-2.0*t*Tin);
+ }
+ }
+ else if(tex->stype==3) { /* diag */
+ Tin= (2.0+x+y)/4.0;
+ }
+ else { /* sphere */
+ Tin= 1.0-sqrt(x*x+ y*y+texvec[2]*texvec[2]);
+ if(Tin<0.0) Tin= 0.0;
+ if(tex->stype==5) Tin*= Tin; /* halo */
+ }
+
+ BRICON;
+ if(tex->flag & TEX_COLORBAND) return do_colorband(tex->coba);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int wood(Tex *tex, float *texvec)
+{
+ float (*noisefunc)(float, float, float, float);
+
+ if(tex->noisetype==TEX_NOISESOFT) noisefunc= BLI_hnoise;
+ else noisefunc= BLI_hnoisep;
+
+
+ if(tex->stype==0) {
+ Tin= 0.5+0.5*sin( (texvec[0]+texvec[1]+texvec[2])*10.0 );
+ }
+ else if(tex->stype==1) {
+ Tin= 0.5+0.5*sin( sqrt(texvec[0]*texvec[0]+texvec[1]*texvec[1]+texvec[2]*texvec[2])*20.0 );
+ }
+ else if(tex->stype==2) {
+ Tin= noisefunc(tex->noisesize, texvec[0], texvec[1], texvec[2]);
+ Tin= 0.5+ 0.5*sin(tex->turbul*Tin+(texvec[0]+texvec[1]+texvec[2])*10.0);
+ }
+ else if(tex->stype==3) {
+ Tin= noisefunc(tex->noisesize, texvec[0], texvec[1], texvec[2]);
+ Tin= 0.5+ 0.5*sin(tex->turbul*Tin+(sqrt(texvec[0]*texvec[0]+texvec[1]*texvec[1]+texvec[2]*texvec[2]))*20.0);
+ }
+
+
+ BRICON;
+ if(tex->flag & TEX_COLORBAND) return do_colorband(tex->coba);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int marble(Tex *tex, float *texvec)
+{
+ float n;
+ float (*turbfunc)(float, float, float, float, int);
+
+ if(tex->noisetype==TEX_NOISESOFT) turbfunc= BLI_turbulence;
+ else turbfunc= BLI_turbulence1;
+
+ n= 5.0*(texvec[0]+texvec[1]+texvec[2]);
+
+ Tin = 0.5+0.5*sin(n+tex->turbul*turbfunc(tex->noisesize, texvec[0],texvec[1],texvec[2], tex->noisedepth));
+
+ switch (tex->stype) {
+ case 1:
+ Tin= sqrt(Tin);
+ break;
+ case 2:
+ Tin= sqrt(Tin);
+ Tin= sqrt(Tin);
+ break;
+ }
+
+ BRICON;
+ if(tex->flag & TEX_COLORBAND) return do_colorband(tex->coba);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int magic(Tex *tex, float *texvec)
+{
+ float x, y, z, turb=1.0;
+ int n;
+
+ n= tex->noisedepth;
+ turb= tex->turbul/5.0;
+
+ x= sin( ( texvec[0]+texvec[1]+texvec[2])*5.0 );
+ y= cos( (-texvec[0]+texvec[1]-texvec[2])*5.0 );
+ z= -cos( (-texvec[0]-texvec[1]+texvec[2])*5.0 );
+ if(n>0) {
+ x*= turb;
+ y*= turb;
+ z*= turb;
+ y= -cos(x-y+z);
+ y*= turb;
+ if(n>1) {
+ x= cos(x-y-z);
+ x*= turb;
+ if(n>2) {
+ z= sin(-x-y-z);
+ z*= turb;
+ if(n>3) {
+ x= -cos(-x+y-z);
+ x*= turb;
+ if(n>4) {
+ y= -sin(-x+y+z);
+ y*= turb;
+ if(n>5) {
+ y= -cos(-x+y+z);
+ y*= turb;
+ if(n>6) {
+ x= cos(x+y+z);
+ x*= turb;
+ if(n>7) {
+ z= sin(x+y-z);
+ z*= turb;
+ if(n>8) {
+ x= -cos(-x-y+z);
+ x*= turb;
+ if(n>9) {
+ y= -sin(x-y+z);
+ y*= turb;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(turb!=0.0) {
+ turb*= 2.0;
+ x/= turb;
+ y/= turb;
+ z/= turb;
+ }
+ Tr= 0.5-x;
+ Tg= 0.5-y;
+ Tb= 0.5-z;
+
+ BRICONRGB;
+ Ta= 1.0;
+
+ return 1;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int stucci(Tex *tex, float *texvec)
+{
+ float b2, vec[3];
+ float ofs;
+ float (*noisefunc)(float, float, float, float);
+
+ if(tex->nor == NULL) return 0;
+
+ if(tex->noisetype==TEX_NOISESOFT) noisefunc= BLI_hnoise;
+ else noisefunc= BLI_hnoisep;
+
+ ofs= tex->turbul/200.0;
+
+ b2= noisefunc(tex->noisesize, texvec[0], texvec[1], texvec[2]);
+ if(tex->stype) ofs*=(b2*b2);
+ vec[0]= b2-noisefunc(tex->noisesize, texvec[0]+ofs, texvec[1], texvec[2]);
+ vec[1]= b2-noisefunc(tex->noisesize, texvec[0], texvec[1]+ofs, texvec[2]);
+ vec[2]= b2-noisefunc(tex->noisesize, texvec[0], texvec[1], texvec[2]+ofs);
+
+ if(tex->stype==1) {
+ tex->nor[0]= vec[0];
+ tex->nor[1]= vec[1];
+ tex->nor[2]= vec[2];
+ }
+ else {
+ tex->nor[0]= -vec[0];
+ tex->nor[1]= -vec[1];
+ tex->nor[2]= -vec[2];
+ }
+
+ return 2;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int texnoise(Tex *tex)
+{
+ float div=3.0;
+ int val, ran, loop;
+
+ ran= BLI_rand();
+ val= (ran & 3);
+
+ loop= tex->noisedepth;
+ while(loop--) {
+ ran= (ran>>2);
+ val*= (ran & 3);
+ div*= 3.0;
+ }
+
+ Tin= ((float)val)/div;;
+
+ BRICON;
+ if(tex->flag & TEX_COLORBAND) return do_colorband(tex->coba);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int plugintex(Tex *tex, float *texvec, float *dxt, float *dyt)
+{
+ PluginTex *pit;
+ int rgbnor=0;
+
+ Tin= 0.0;
+
+ pit= tex->plugin;
+ if(pit && pit->doit) {
+ VECCOPY(pit->result+5, R.vn);
+
+ if(R.osatex) rgbnor= ((TexDoit)pit->doit)(tex->stype, pit->data, texvec, dxt, dyt);
+ else rgbnor= ((TexDoit)pit->doit)(tex->stype, pit->data, texvec, 0, 0);
+
+ Tin= pit->result[0];
+
+ if(rgbnor & TEX_NOR) {
+ if(tex->nor) {
+ VECCOPY(tex->nor, pit->result+5);
+ }
+ }
+
+ if(rgbnor & TEX_RGB) {
+ Tr= pit->result[1];
+ Tg= pit->result[2];
+ Tb= pit->result[3];
+ Ta= pit->result[4];
+
+ BRICONRGB;
+ }
+
+ BRICON;
+ if(tex->flag & TEX_COLORBAND) rgbnor |= do_colorband(tex->coba);
+ }
+
+ return rgbnor;
+}
+
+/* *************** PROJEKTIES ******************* */
+
+void tubemap(float x, float y, float z, float *adr1, float *adr2)
+{
+ float len;
+
+ *adr2 = (z + 1.0) / 2.0;
+
+ len= sqrt(x*x+y*y);
+ if(len>0) {
+ *adr1 = (1.0 - (atan2(x/len,y/len) / M_PI)) / 2.0;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void spheremap(float x, float y, float z, float *adr1, float *adr2)
+{
+ float len;
+
+ len= sqrt(x*x+y*y+z*z);
+ if(len>0.0) {
+
+ if(x==0.0 && y==0.0) *adr1= 0.0; /* anders domain error */
+ else *adr1 = (1.0 - atan2(x,y)/M_PI )/2.0;
+
+ z/=len;
+ *adr2 = 1.0- saacos(z)/M_PI;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int cubemap_glob(MTex *mtex, float x, float y, float z, float *adr1, float *adr2)
+{
+ float x1, y1, z1, nor[3];
+ int ret;
+
+ VECCOPY(nor, R.vn);
+ MTC_Mat4Mul3Vecfl(R.viewinv, nor);
+
+ x1= fabs(nor[0]);
+ y1= fabs(nor[1]);
+ z1= fabs(nor[2]);
+
+ if(z1>=x1 && z1>=y1) {
+ *adr1 = (x + 1.0) / 2.0;
+ *adr2 = (y + 1.0) / 2.0;
+ ret= 0;
+ }
+ else if(y1>=x1 && y1>=z1) {
+ *adr1 = (x + 1.0) / 2.0;
+ *adr2 = (z + 1.0) / 2.0;
+ ret= 1;
+ }
+ else {
+ *adr1 = (y + 1.0) / 2.0;
+ *adr2 = (z + 1.0) / 2.0;
+ ret= 2;
+ }
+ return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int cubemap(MTex *mtex, float x, float y, float z, float *adr1, float *adr2)
+{
+ int proj[4], ret= 0;
+
+ if(R.vlr && R.vlr->mface) {
+ int index;
+ /* the mtex->proj{xyz} have type char. maybe this should be wider? */
+ /* casting to int ensures that the index type is right. */
+ index = (int) mtex->projx;
+ proj[index]= ME_PROJXY;
+
+ index = (int) mtex->projy;
+ proj[index]= ME_PROJXZ;
+
+ index = (int) mtex->projz;
+ proj[index]= ME_PROJYZ;
+
+ if(R.vlr->mface->puno & proj[1]) {
+ *adr1 = (x + 1.0) / 2.0;
+ *adr2 = (y + 1.0) / 2.0;
+ }
+ else if(R.vlr->mface->puno & proj[2]) {
+ *adr1 = (x + 1.0) / 2.0;
+ *adr2 = (z + 1.0) / 2.0;
+ ret= 1;
+ }
+ else {
+ *adr1 = (y + 1.0) / 2.0;
+ *adr2 = (z + 1.0) / 2.0;
+ ret= 2;
+ }
+ } else
+ return cubemap_glob(mtex, x, y, z, adr1, adr2);
+
+ return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int cubemap_ob(MTex *mtex, float x, float y, float z, float *adr1, float *adr2)
+{
+ float x1, y1, z1, nor[3];
+ int ret;
+
+ VECCOPY(nor, R.vn);
+ if(mtex->object) MTC_Mat4Mul3Vecfl(mtex->object->imat, nor);
+
+ x1= fabs(nor[0]);
+ y1= fabs(nor[1]);
+ z1= fabs(nor[2]);
+
+ if(z1>=x1 && z1>=y1) {
+ *adr1 = (x + 1.0) / 2.0;
+ *adr2 = (y + 1.0) / 2.0;
+ ret= 0;
+ }
+ else if(y1>=x1 && y1>=z1) {
+ *adr1 = (x + 1.0) / 2.0;
+ *adr2 = (z + 1.0) / 2.0;
+ ret= 1;
+ }
+ else {
+ *adr1 = (y + 1.0) / 2.0;
+ *adr2 = (z + 1.0) / 2.0;
+ ret= 2;
+ }
+ return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void do_2d_mapping(MTex *mtex, float *t, float *dxt, float *dyt)
+{
+ Tex *tex;
+ float fx, fy, fac1, area[8];
+ int ok, proj, areaflag= 0, wrap;
+
+ wrap= mtex->mapping;
+ tex= mtex->tex;
+
+ if(R.osa==0) {
+
+ if(wrap==MTEX_FLAT) {
+ fx = (t[0] + 1.0) / 2.0;
+ fy = (t[1] + 1.0) / 2.0;
+ }
+ else if(wrap==MTEX_TUBE) tubemap(t[0], t[1], t[2], &fx, &fy);
+ else if(wrap==MTEX_SPHERE) spheremap(t[0], t[1], t[2], &fx, &fy);
+ else {
+ if(mtex->texco==TEXCO_OBJECT) cubemap_ob(mtex, t[0], t[1], t[2], &fx, &fy);
+ else if(mtex->texco==TEXCO_GLOB) cubemap_glob(mtex, t[0], t[1], t[2], &fx, &fy);
+ else cubemap(mtex, t[0], t[1], t[2], &fx, &fy);
+ }
+
+ /* repeat */
+ if(tex->xrepeat>1) {
+ fx *= tex->xrepeat;
+ if(fx>1.0) fx -= (int)(fx);
+ else if(fx<0.0) fx+= 1-(int)(fx);
+ }
+ if(tex->yrepeat>1) {
+ fy *= tex->yrepeat;
+ if(fy>1.0) fy -= (int)(fy);
+ else if(fy<0.0) fy+= 1-(int)(fy);
+ }
+
+ /* crop */
+ if(tex->cropxmin!=0.0 || tex->cropxmax!=1.0) {
+ fac1= tex->cropxmax - tex->cropxmin;
+ fx= tex->cropxmin+ fx*fac1;
+ }
+ if(tex->cropymin!=0.0 || tex->cropymax!=1.0) {
+ fac1= tex->cropymax - tex->cropymin;
+ fy= tex->cropymin+ fy*fac1;
+ }
+
+ t[0]= fx;
+ t[1]= fy;
+ }
+ else {
+
+ if(wrap==MTEX_FLAT) {
+ fx= (t[0] + 1.0) / 2.0;
+ fy= (t[1] + 1.0) / 2.0;
+ dxt[0]/= 2.0;
+ dxt[1]/= 2.0;
+ dyt[0]/= 2.0;
+ dyt[1]/= 2.0;
+ }
+ else if ELEM(wrap, MTEX_TUBE, MTEX_SPHERE) {
+ /* uitzondering: de naad achter (y<0.0) */
+ ok= 1;
+ if(t[1]<=0.0) {
+ fx= t[0]+dxt[0];
+ fy= t[0]+dyt[0];
+ if(fx>=0.0 && fy>=0.0 && t[0]>=0.0);
+ else if(fx<=0.0 && fy<=0.0 && t[0]<=0.0);
+ else ok= 0;
+ }
+ if(ok) {
+ if(wrap==MTEX_TUBE) {
+ tubemap(t[0], t[1], t[2], area, area+1);
+ tubemap(t[0]+dxt[0], t[1]+dxt[1], t[2]+dxt[2], area+2, area+3);
+ tubemap(t[0]+dyt[0], t[1]+dyt[1], t[2]+dyt[2], area+4, area+5);
+ }
+ else {
+ spheremap(t[0], t[1], t[2],area,area+1);
+ spheremap(t[0]+dxt[0], t[1]+dxt[1], t[2]+dxt[2], area+2, area+3);
+ spheremap(t[0]+dyt[0], t[1]+dyt[1], t[2]+dyt[2], area+4, area+5);
+ }
+ areaflag= 1;
+ }
+ else {
+ if(wrap==MTEX_TUBE) tubemap(t[0], t[1], t[2], &fx, &fy);
+ else spheremap(t[0], t[1], t[2], &fx, &fy);
+ dxt[0]/= 2.0;
+ dxt[1]/= 2.0;
+ dyt[0]/= 2.0;
+ dyt[1]/= 2.0;
+ }
+ }
+ else {
+
+ if(mtex->texco==TEXCO_OBJECT) proj = cubemap_ob(mtex, t[0], t[1], t[2], &fx, &fy);
+ else if (mtex->texco==TEXCO_GLOB) proj = cubemap_glob(mtex, t[0], t[1], t[2], &fx, &fy);
+ else proj = cubemap(mtex, t[0], t[1], t[2], &fx, &fy);
+
+ if(proj==1) {
+ dxt[1]= dxt[2];
+ dyt[1]= dyt[2];
+ }
+ else if(proj==2) {
+ dxt[0]= dxt[1];
+ dyt[0]= dyt[1];
+ dxt[1]= dxt[2];
+ dyt[1]= dyt[2];
+ }
+ dxt[0]/= 2.0;
+ dxt[1]/= 2.0;
+ dyt[0]/= 2.0;
+ dyt[1]/= 2.0;
+ }
+
+ /* als area dan dxt[] en dyt[] opnieuw berekenen */
+ if(areaflag) {
+ fx= area[0];
+ fy= area[1];
+ dxt[0]= area[2]-fx;
+ dxt[1]= area[3]-fy;
+ dyt[0]= area[4]-fx;
+ dyt[1]= area[5]-fy;
+ }
+
+ /* repeat */
+ if(tex->xrepeat>1) {
+ fx *= tex->xrepeat;
+ dxt[0]*= tex->xrepeat;
+ dyt[0]*= tex->xrepeat;
+ if(fx>1.0) fx -= (int)(fx);
+ else if(fx<0.0) fx+= 1-(int)(fx);
+ }
+ if(tex->yrepeat>1) {
+ fy *= tex->yrepeat;
+ dxt[1]*= tex->yrepeat;
+ dyt[1]*= tex->yrepeat;
+ if(fy>1.0) fy -= (int)(fy);
+ else if(fy<0.0) fy+= 1-(int)(fy);
+ }
+
+ /* crop */
+ if(tex->cropxmin!=0.0 || tex->cropxmax!=1.0) {
+ fac1= tex->cropxmax - tex->cropxmin;
+ fx= tex->cropxmin+ fx*fac1;
+ dxt[0]*= fac1;
+ dyt[0]*= fac1;
+ }
+ if(tex->cropymin!=0.0 || tex->cropymax!=1.0) {
+ fac1= tex->cropymax - tex->cropymin;
+ fy= tex->cropymin+ fy*fac1;
+ dxt[1]*= fac1;
+ dyt[1]*= fac1;
+ }
+
+ t[0]= fx;
+ t[1]= fy;
+
+ }
+}
+
+
+/* ************************************** */
+
+int multitex(Tex *tex, float *texvec, float *dxt, float *dyt)
+{
+
+
+ switch(tex->type) {
+
+ case 0:
+ Tin= 0.0;
+ return 0;
+ case TEX_CLOUDS:
+ return clouds(tex, texvec);
+ case TEX_WOOD:
+ return wood(tex, texvec);
+ case TEX_MARBLE:
+ return marble(tex, texvec);
+ case TEX_MAGIC:
+ return magic(tex, texvec);
+ case TEX_BLEND:
+ return blend(tex, texvec);
+ case TEX_STUCCI:
+ Tin= 0.0;
+ return stucci(tex, texvec);
+ case TEX_NOISE:
+ return texnoise(tex);
+ case TEX_IMAGE:
+ if(R.osatex) return imagewraposa(tex, texvec, dxt, dyt);
+ else return imagewrap(tex, texvec);
+ break;
+ case TEX_PLUGIN:
+ return plugintex(tex, texvec, dxt, dyt);
+ break;
+ case TEX_ENVMAP:
+ return RE_envmaptex(tex, texvec, dxt, dyt);
+ break;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void do_material_tex()
+{
+ Object *ob;
+ Material *mat_col, *mat_colspec, *mat_colmir, *mat_ref;
+ Material *mat_spec, *mat_har, *mat_emit, *mat_alpha;
+ MTex *mtex;
+ Tex *tex;
+ float *co = NULL, *dx = NULL, *dy = NULL, fact,
+ facm, factt, facmm, facmul = 0.0, stencilTin=1.0;
+ float texvec[3], dxt[3], dyt[3], tempvec[3], norvec[3];
+ int tex_nr, rgbnor= 0;
+
+ /* hier flag testen of er wel tex is */
+
+ mat_col=mat_colspec=mat_colmir=mat_ref=mat_spec=mat_har=mat_emit=mat_alpha= R.mat;
+
+ tex_nr= 0;
+ if(R.mat->septex) tex_nr= R.mat->texact;
+
+ for(; tex_nr<8; tex_nr++) {
+ if(R.mat->mtex[tex_nr]) {
+ mtex= R.mat->mtex[tex_nr];
+
+ tex= mtex->tex;
+ if(tex==0) continue;
+
+ /* welke coords */
+ if(mtex->texco==TEXCO_ORCO) {
+ co= R.lo; dx= O.dxlo; dy= O.dylo;
+ }
+ else if(mtex->texco==TEXCO_STICKY) {
+ co= R.sticky; dx= O.dxsticky; dy= O.dysticky;
+ }
+ else if(mtex->texco==TEXCO_OBJECT) {
+ ob= mtex->object;
+ if(ob) {
+ co= tempvec;
+ dx= dxt;
+ dy= dyt;
+ VECCOPY(tempvec, R.co);
+ MTC_Mat4MulVecfl(ob->imat, tempvec);
+ if(R.osatex) {
+ VECCOPY(dxt, O.dxco);
+ VECCOPY(dyt, O.dyco);
+ MTC_Mat4Mul3Vecfl(ob->imat, dxt);
+ MTC_Mat4Mul3Vecfl(ob->imat, dyt);
+ }
+ }
+ else {
+ /* als object niet bestaat geen orco's gebruiken (zijn niet geinitialiseerd */
+ co= R.co;
+ dx= O.dxco; dy= O.dyco;
+ }
+ }
+ else if(mtex->texco==TEXCO_REFL) {
+ co= R.ref; dx= O.dxref; dy= O.dyref;
+ }
+ else if(mtex->texco==TEXCO_NORM) {
+ co= R.orn; dx= O.dxno; dy= O.dyno;
+ }
+ else if(mtex->texco==TEXCO_GLOB) {
+ co= R.gl; dx= O.dxco; dy= O.dyco;
+ }
+ else if(mtex->texco==TEXCO_UV) {
+ co= R.uv; dx= O.dxuv; dy= O.dyuv;
+ }
+ else if(mtex->texco==TEXCO_WINDOW) {
+ co= R.winco; dx= O.dxwin; dy= O.dywin;
+ }
+
+ /* de pointer defines if bumping happens */
+ if(mtex->mapto & MAP_NORM) {
+ tex->nor= norvec;
+ norvec[0]= norvec[1]= norvec[2]= 0.0;
+ }
+ else tex->nor= 0;
+
+ if(tex->type==TEX_IMAGE) {
+
+ /* nieuw: eerst coords verwisselen, dan map, dan trans/scale */
+
+ /* placement */
+ if(mtex->projx) texvec[0]= co[mtex->projx-1];
+ else texvec[0]= 0.0;
+ if(mtex->projy) texvec[1]= co[mtex->projy-1];
+ else texvec[1]= 0.0;
+ if(mtex->projz) texvec[2]= co[mtex->projz-1];
+ else texvec[2]= 0.0;
+
+ if(R.osatex) {
+
+ if(mtex->projx) {
+ dxt[0]= dx[mtex->projx-1];
+ dyt[0]= dy[mtex->projx-1];
+ }
+ else dxt[0]= 0.0;
+ if(mtex->projy) {
+ dxt[1]= dx[mtex->projy-1];
+ dyt[1]= dy[mtex->projy-1];
+ }
+ else dxt[1]= 0.0;
+ if(mtex->projx) {
+ dxt[2]= dx[mtex->projz-1];
+ dyt[2]= dy[mtex->projz-1];
+ }
+ else dxt[2]= 0.0;
+ }
+
+ do_2d_mapping(mtex, texvec, dxt, dyt);
+
+ /* translate en scale */
+ texvec[0]= mtex->size[0]*(texvec[0]-0.5) +mtex->ofs[0]+0.5;
+ texvec[1]= mtex->size[1]*(texvec[1]-0.5) +mtex->ofs[1]+0.5;
+ if(R.osatex) {
+ dxt[0]= mtex->size[0]*dxt[0];
+ dxt[1]= mtex->size[1]*dxt[1];
+ dyt[0]= mtex->size[0]*dyt[0];
+ dyt[1]= mtex->size[1]*dyt[1];
+ }
+ }
+ else {
+
+ /* placement */
+ if(mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]);
+ else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
+
+ if(mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]);
+ else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
+
+ if(mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]);
+ else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
+
+ if(R.osatex) {
+ if(mtex->projx) {
+ dxt[0]= mtex->size[0]*dx[mtex->projx-1];
+ dyt[0]= mtex->size[0]*dy[mtex->projx-1];
+ }
+ else dxt[0]= 0.0;
+ if(mtex->projy) {
+ dxt[1]= mtex->size[1]*dx[mtex->projy-1];
+ dyt[1]= mtex->size[1]*dy[mtex->projy-1];
+ }
+ else dxt[1]= 0.0;
+ if(mtex->projx) {
+ dxt[2]= mtex->size[2]*dx[mtex->projz-1];
+ dyt[2]= mtex->size[2]*dy[mtex->projz-1];
+ }
+ else dxt[2]= 0.0;
+ }
+ }
+
+ rgbnor= multitex(tex, texvec, dxt, dyt);
+
+ /* texture output */
+
+ if( (rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
+ Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+ rgbnor-= 1;
+ }
+ if(mtex->texflag & MTEX_NEGATIVE) {
+ if(rgbnor & TEX_RGB) {
+ Tr= 1.0-Tr;
+ Tg= 1.0-Tg;
+ Tb= 1.0-Tb;
+ }
+ Tin= 1.0-Tin;
+ }
+ if(mtex->texflag & MTEX_STENCIL) {
+ if(rgbnor & TEX_RGB) {
+ fact= Ta;
+ Ta*= stencilTin;
+ stencilTin*= fact;
+ }
+ else {
+ fact= Tin;
+ Tin*= stencilTin;
+ stencilTin*= fact;
+ }
+ }
+ else {
+ if(rgbnor & TEX_RGB) Ta*= stencilTin;
+ else Tin*= stencilTin;
+ }
+
+ if(tex->nor && (rgbnor & TEX_NOR)==0) {
+ /* make our own normal */
+ if(rgbnor & TEX_RGB) {
+ tex->nor[0]= Tr;
+ tex->nor[1]= Tg;
+ tex->nor[2]= Tb;
+ }
+ else {
+ float co= 0.5*cos(Tin-0.5);
+ float si= 0.5*sin(Tin-0.5);
+ float f1, f2;
+
+ f1= R.vn[0];
+ f2= R.vn[1];
+ tex->nor[0]= f1*co+f2*si;
+ tex->nor[1]= f2*co-f1*si;
+ f1= R.vn[1];
+ f2= R.vn[2];
+ tex->nor[1]= f1*co+f2*si;
+ tex->nor[2]= f2*co-f1*si;
+ }
+ }
+
+
+ /* mapping */
+ if(mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) {
+
+ if((rgbnor & TEX_RGB)==0) {
+ Tr= mtex->r;
+ Tg= mtex->g;
+ Tb= mtex->b;
+ }
+ else if(mtex->mapto & MAP_ALPHA) {
+ if(mtex->texflag & MTEX_ALPHAMIX) Tin= Ta;
+ else Tin= stencilTin;
+ }
+ else Tin= Ta;
+
+ fact= Tin*mtex->colfac;
+ facm= 1.0-fact;
+ if(mtex->blendtype==MTEX_MUL) facm= 1.0-mtex->colfac;
+ if(mtex->blendtype==MTEX_SUB) fact= -fact;
+
+ if(mtex->mapto & MAP_COL) {
+ if(mtex->blendtype==MTEX_BLEND) {
+ R.matren->r= (fact*Tr + facm*mat_col->r);
+ R.matren->g= (fact*Tg + facm*mat_col->g);
+ R.matren->b= (fact*Tb + facm*mat_col->b);
+ }
+ else if(mtex->blendtype==MTEX_MUL) {
+ R.matren->r= (facm+fact*Tr)*mat_col->r;
+ R.matren->g= (facm+fact*Tg)*mat_col->g;
+ R.matren->b= (facm+fact*Tb)*mat_col->b;
+ }
+ else {
+ R.matren->r= (fact*Tr + mat_col->r);
+ R.matren->g= (fact*Tg + mat_col->g);
+ R.matren->b= (fact*Tb + mat_col->b);
+ }
+ mat_col= R.matren;
+ }
+ if(mtex->mapto & MAP_COLSPEC) {
+ if(mtex->blendtype==MTEX_BLEND) {
+ R.matren->specr= (fact*Tr + facm*mat_colspec->specr);
+ R.matren->specg= (fact*Tg + facm*mat_colspec->specg);
+ R.matren->specb= (fact*Tb + facm*mat_colspec->specb);
+ }
+ else if(mtex->blendtype==MTEX_MUL) {
+ R.matren->specr= (facm+fact*Tr)*mat_colspec->specr;
+ R.matren->specg= (facm+fact*Tg)*mat_colspec->specg;
+ R.matren->specb= (facm+fact*Tb)*mat_colspec->specb;
+ }
+ else {
+ R.matren->specr= (fact*Tr + mat_colspec->specr);
+ R.matren->specg= (fact*Tg + mat_colspec->specg);
+ R.matren->specb= (fact*Tb + mat_colspec->specb);
+ }
+ mat_colspec= R.matren;
+ }
+ if(mtex->mapto & MAP_COLMIR) {
+ if(mtex->blendtype==MTEX_BLEND) {
+ R.refcol[0]= fact + facm*R.refcol[0];
+
+ R.refcol[1]= fact*Tr + facm*R.refcol[1];
+ R.refcol[2]= fact*Tg + facm*R.refcol[2];
+ R.refcol[3]= fact*Tb + facm*R.refcol[3];
+ }
+ else if(mtex->blendtype==MTEX_MUL) {
+ R.matren->mirr= (facm+fact*Tr)*mat_colmir->mirr;
+ R.matren->mirg= (facm+fact*Tg)*mat_colmir->mirg;
+ R.matren->mirb= (facm+fact*Tb)*mat_colmir->mirb;
+ }
+ else {
+ R.matren->mirr= (fact*Tr + mat_colmir->mirr);
+ R.matren->mirg= (fact*Tg + mat_colmir->mirg);
+ R.matren->mirb= (fact*Tb + mat_colmir->mirb);
+ }
+ mat_colmir= R.matren;
+ }
+ }
+ if( (mtex->mapto & MAP_NORM) ) {
+ if(tex->nor) {
+
+ if(mtex->maptoneg & MAP_NORM) tex->norfac= -mtex->norfac;
+ else tex->norfac= mtex->norfac;
+
+ R.vn[0]+= tex->norfac*tex->nor[0];
+ R.vn[1]+= tex->norfac*tex->nor[1];
+ R.vn[2]+= tex->norfac*tex->nor[2];
+
+ Normalise(R.vn);
+
+ /* hierdoor wordt de bump aan de volgende texture doorgegeven */
+ R.orn[0]= R.vn[0];
+ R.orn[1]= -R.vn[1];
+ R.orn[2]= R.vn[2];
+
+ /* reflection vector */
+ RE_calc_R_ref();
+ }
+ }
+
+ if(mtex->mapto & MAP_VARS) {
+ if(rgbnor & TEX_RGB) {
+ if(Talpha) Tin= Ta;
+ else Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+ }
+
+ fact= Tin*mtex->varfac;
+ facm= 1.0-fact;
+ if(mtex->blendtype==MTEX_MUL) facmul= 1.0-mtex->varfac;
+ if(mtex->blendtype==MTEX_SUB) fact= -fact;
+
+ if(mtex->mapto & MAP_REF) {
+ if(mtex->maptoneg & MAP_REF) {factt= facm; facmm= fact;}
+ else {factt= fact; facmm= facm;}
+
+ if(mtex->blendtype==MTEX_BLEND)
+ R.matren->ref= factt*mtex->def_var+ facmm*mat_ref->ref;
+ else if(mtex->blendtype==MTEX_MUL)
+ R.matren->ref= (facmul+factt)*mat_ref->ref;
+ else {
+ R.matren->ref= factt+mat_ref->ref;
+ if(R.matren->ref<0.0) R.matren->ref= 0.0;
+ }
+ mat_ref= R.matren;
+ }
+ if(mtex->mapto & MAP_SPEC) {
+ if(mtex->maptoneg & MAP_SPEC) {factt= facm; facmm= fact;}
+ else {factt= fact; facmm= facm;}
+
+ if(mtex->blendtype==MTEX_BLEND)
+ R.matren->spec= factt*mtex->def_var+ facmm*mat_spec->spec;
+ else if(mtex->blendtype==MTEX_MUL)
+ R.matren->spec= (facmul+factt)*mat_spec->spec;
+ else {
+ R.matren->spec= factt+mat_spec->spec;
+ if(R.matren->spec<0.0) R.matren->spec= 0.0;
+ }
+ mat_spec= R.matren;
+ }
+ if(mtex->mapto & MAP_EMIT) {
+ if(mtex->maptoneg & MAP_EMIT) {factt= facm; facmm= fact;}
+ else {factt= fact; facmm= facm;}
+
+ if(mtex->blendtype==MTEX_BLEND)
+ R.matren->emit= factt*mtex->def_var+ facmm*mat_emit->emit;
+ else if(mtex->blendtype==MTEX_MUL)
+ R.matren->emit= (facmul+factt)*mat_emit->emit;
+ else {
+ R.matren->emit= factt+mat_emit->emit;
+ if(R.matren->emit<0.0) R.matren->emit= 0.0;
+ }
+ mat_emit= R.matren;
+ }
+ if(mtex->mapto & MAP_ALPHA) {
+ if(mtex->maptoneg & MAP_ALPHA) {factt= facm; facmm= fact;}
+ else {factt= fact; facmm= facm;}
+
+ if(mtex->blendtype==MTEX_BLEND)
+ R.matren->alpha= factt*mtex->def_var+ facmm*mat_alpha->alpha;
+ else if(mtex->blendtype==MTEX_MUL)
+ R.matren->alpha= (facmul+factt)*mat_alpha->alpha;
+ else {
+ R.matren->alpha= factt+mat_alpha->alpha;
+ if(R.matren->alpha<0.0) R.matren->alpha= 0.0;
+ else if(R.matren->alpha>1.0) R.matren->alpha= 1.0;
+ }
+ mat_alpha= R.matren;
+ }
+ if(mtex->mapto & MAP_HAR) {
+ if(mtex->maptoneg & MAP_HAR) {factt= facm; facmm= fact;}
+ else {factt= fact; facmm= facm;}
+
+ if(mtex->blendtype==MTEX_BLEND) {
+ R.matren->har= 128.0*factt*mtex->def_var+ facmm*mat_har->har;
+ } else if(mtex->blendtype==MTEX_MUL) {
+ R.matren->har= (facmul+factt)*mat_har->har;
+ } else {
+ R.matren->har= 128.0*factt+mat_har->har;
+ if(R.matren->har<1) R.matren->har= 1;
+ }
+ mat_har= R.matren;
+ }
+ }
+ }
+
+ if(R.mat->septex) break;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void do_halo_tex(HaloRen *har, float xn, float yn, float *colf)
+{
+ MTex *mtex;
+ float texvec[3], dxt[3], dyt[3], fact, facm, dx;
+ int rgb;
+
+ mtex= har->mat->mtex[0];
+ if(mtex->tex==0) return;
+ /* no normal mapping */
+ mtex->tex->nor= 0;
+
+ texvec[0]= xn/har->rad;
+ texvec[1]= yn/har->rad;
+ texvec[2]= 0.0;
+
+ R.osatex= (har->mat->texco & TEXCO_OSA);
+
+ /* placement */
+ if(mtex->projx) texvec[0]= mtex->size[0]*(texvec[mtex->projx-1]+mtex->ofs[0]);
+ else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
+
+ if(mtex->projy) texvec[1]= mtex->size[1]*(texvec[mtex->projy-1]+mtex->ofs[1]);
+ else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
+
+ if(mtex->projz) texvec[2]= mtex->size[2]*(texvec[mtex->projz-1]+mtex->ofs[2]);
+ else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
+
+ if(R.osatex) {
+
+ dx= 1.0/har->rad;
+
+ if(mtex->projx) {
+ dxt[0]= mtex->size[0]*dx;
+ dyt[0]= mtex->size[0]*dx;
+ }
+ else dxt[0]= 0.0;
+ if(mtex->projy) {
+ dxt[1]= mtex->size[1]*dx;
+ dyt[1]= mtex->size[1]*dx;
+ }
+ else dxt[1]= 0.0;
+ if(mtex->projz) {
+ dxt[2]= 0.0;
+ dyt[2]= 0.0;
+ }
+ else dxt[2]= 0.0;
+
+ }
+
+
+ if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, dxt, dyt);
+
+ rgb= multitex(mtex->tex, texvec, dxt, dyt);
+
+ /* texture uitgang */
+ if(rgb && (mtex->texflag & MTEX_RGBTOINT)) {
+ Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+ rgb= 0;
+ }
+ if(mtex->texflag & MTEX_NEGATIVE) {
+ if(rgb) {
+ Tr= 1.0-Tr;
+ Tg= 1.0-Tg;
+ Tb= 1.0-Tb;
+ }
+ else Tin= 1.0-Tin;
+ }
+
+ /* mapping */
+ if(mtex->mapto & MAP_COL) {
+
+ if(rgb==0) {
+ Tr= mtex->r;
+ Tg= mtex->g;
+ Tb= mtex->b;
+ }
+ else if(mtex->mapto & MAP_ALPHA) {
+ if(mtex->texflag & MTEX_ALPHAMIX) Tin= Ta;
+ else Tin= 1.0;
+ }
+ else Tin= Ta;
+
+ fact= Tin*mtex->colfac;
+ facm= 1.0-fact;
+
+ if(mtex->blendtype==MTEX_MUL) {
+ facm= 1.0-mtex->colfac;
+ }
+ else fact*= 256;
+
+ if(mtex->blendtype==MTEX_SUB) fact= -fact;
+
+ if(mtex->blendtype==MTEX_BLEND) {
+ colf[0]= (fact*Tr + facm*har->r);
+ colf[1]= (fact*Tg + facm*har->g);
+ colf[2]= (fact*Tb + facm*har->b);
+ }
+ else if(mtex->blendtype==MTEX_MUL) {
+ colf[0]= (facm+fact*Tr)*har->r;
+ colf[1]= (facm+fact*Tg)*har->g;
+ colf[2]= (facm+fact*Tb)*har->b;
+ }
+ else {
+ colf[0]= (fact*Tr + har->r);
+ colf[1]= (fact*Tg + har->g);
+ colf[2]= (fact*Tb + har->b);
+
+ CLAMP(colf[0], 0.0, 1.0);
+ CLAMP(colf[1], 0.0, 1.0);
+ CLAMP(colf[2], 0.0, 1.0);
+ }
+ }
+ if(mtex->mapto & MAP_ALPHA) {
+ if(rgb) {
+ if(Talpha) Tin= Ta;
+ else Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+ }
+
+ colf[3]*= Tin;
+ }
+
+ R.osatex= 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void do_sky_tex()
+{
+ World *wrld_hor, *wrld_zen;
+ MTex *mtex;
+ float *co, fact, facm, factt, facmm, facmul = 0.0, stencilTin=1.0;
+ float tempvec[3], texvec[3], dxt[3], dyt[3];
+ int tex_nr, rgb= 0, ok;
+
+
+ /* hier flag testen of er wel tex is */
+
+ wrld_hor= wrld_zen= G.scene->world;
+
+ /* The 6 here is rather arbitrary, it seems. */
+ for(tex_nr=0; tex_nr<6; tex_nr++) {
+ if(R.wrld.mtex[tex_nr]) {
+ mtex= R.wrld.mtex[tex_nr];
+
+ if(mtex->tex==0) continue;
+ /* if(mtex->mapto==0) continue; */
+
+ /* welke coords */
+ co= R.lo;
+
+ /* Grab the mapping settings for this texture */
+ if(mtex->texco==TEXCO_OBJECT) {
+ Object *ob= mtex->object;
+ if(ob) {
+ VECCOPY(tempvec, R.lo);
+ MTC_Mat4MulVecfl(ob->imat, tempvec);
+ co= tempvec;
+ }
+ }
+
+ /* placement */
+ if(mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]);
+ else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
+
+ if(mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]);
+ else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
+
+ if(mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]);
+ else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
+
+ /* texture */
+ if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, dxt, dyt);
+
+ rgb= multitex(mtex->tex, texvec, dxt, dyt);
+
+ /* texture uitgang */
+ if(rgb && (mtex->texflag & MTEX_RGBTOINT)) {
+ Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+ rgb= 0;
+ }
+ if(mtex->texflag & MTEX_NEGATIVE) {
+ if(rgb) {
+ Tr= 1.0-Tr;
+ Tg= 1.0-Tg;
+ Tb= 1.0-Tb;
+ }
+ else Tin= 1.0-Tin;
+ }
+ if(mtex->texflag & MTEX_STENCIL) {
+ if(rgb) {
+
+ }
+ else {
+ fact= Tin;
+ Tin*= stencilTin;
+ stencilTin*= fact;
+ }
+ }
+ else {
+ if(rgb) ;
+ else Tin*= stencilTin;
+ }
+
+ /* colour mapping */
+ if(mtex->mapto & (WOMAP_HORIZ+WOMAP_ZENUP+WOMAP_ZENDOWN)) {
+
+ if(rgb==0) {
+ Tr= mtex->r;
+ Tg= mtex->g;
+ Tb= mtex->b;
+ }
+ else Tin= 1.0;
+
+ fact= Tin*mtex->colfac;
+ facm= 1.0-fact;
+ if(mtex->blendtype==MTEX_MUL) facm= 1.0-mtex->colfac;
+ if(mtex->blendtype==MTEX_SUB) fact= -fact;
+
+ if(mtex->mapto & WOMAP_HORIZ) {
+ if(mtex->blendtype==MTEX_BLEND) {
+ R.wrld.horr= (fact*Tr + facm*wrld_hor->horr);
+ R.wrld.horg= (fact*Tg + facm*wrld_hor->horg);
+ R.wrld.horb= (fact*Tb + facm*wrld_hor->horb);
+ }
+ else if(mtex->blendtype==MTEX_MUL) {
+ R.wrld.horr= (facm+fact*Tr)*wrld_hor->horr;
+ R.wrld.horg= (facm+fact*Tg)*wrld_hor->horg;
+ R.wrld.horb= (facm+fact*Tb)*wrld_hor->horb;
+ }
+ else {
+ R.wrld.horr= (fact*Tr + wrld_hor->horr);
+ R.wrld.horg= (fact*Tg + wrld_hor->horg);
+ R.wrld.horb= (fact*Tb + wrld_hor->horb);
+ }
+ wrld_hor= &R.wrld;
+ }
+ if(mtex->mapto & (WOMAP_ZENUP+WOMAP_ZENDOWN)) {
+ ok= 0;
+ if(R.wrld.skytype & WO_SKYREAL) {
+ if((R.wrld.skytype & WO_ZENUP)) {
+ if(mtex->mapto & WOMAP_ZENUP) ok= 1;
+ }
+ else if(mtex->mapto & WOMAP_ZENDOWN) ok= 1;
+ }
+ else ok= 1;
+
+ if(ok) {
+
+ if(mtex->blendtype==MTEX_BLEND) {
+ R.wrld.zenr= (fact*Tr + facm*wrld_zen->zenr);
+ R.wrld.zeng= (fact*Tg + facm*wrld_zen->zeng);
+ R.wrld.zenb= (fact*Tb + facm*wrld_zen->zenb);
+ }
+ else if(mtex->blendtype==MTEX_MUL) {
+ R.wrld.zenr= (facm+fact*Tr)*wrld_zen->zenr;
+ R.wrld.zeng= (facm+fact*Tg)*wrld_zen->zeng;
+ R.wrld.zenb= (facm+fact*Tb)*wrld_zen->zenb;
+ }
+ else {
+ R.wrld.zenr= (fact*Tr + wrld_zen->zenr);
+ R.wrld.zeng= (fact*Tg + wrld_zen->zeng);
+ R.wrld.zenb= (fact*Tb + wrld_zen->zenb);
+ }
+ wrld_zen= &R.wrld;
+ }
+ else {
+ /* anders blijft zenRGB hangen */
+ R.wrld.zenr= wrld_zen->zenr;
+ R.wrld.zeng= wrld_zen->zeng;
+ R.wrld.zenb= wrld_zen->zenb;
+ }
+ }
+ }
+ if(mtex->mapto & WOMAP_BLEND) {
+ if(rgb) Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+
+ fact= Tin*mtex->varfac;
+ facm= 1.0-fact;
+ if(mtex->blendtype==MTEX_MUL) facmul= 1.0-mtex->varfac;
+ if(mtex->blendtype==MTEX_SUB) fact= -fact;
+
+ factt= fact; facmm= facm;
+
+ if(mtex->blendtype==MTEX_BLEND)
+ R.inprz= factt*mtex->def_var+ facmm*R.inprz;
+ else if(mtex->blendtype==MTEX_MUL)
+ R.inprz= (facmul+factt)*R.inprz;
+ else {
+ R.inprz= factt+R.inprz;
+ }
+ }
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* explicit lampren stuff should be factored out! or rather, the
+ texturing stuff might need to go...*/
+void do_lamp_tex(LampRen *la, float *lavec)
+{
+ Object *ob;
+ LampRen *la_col;
+ MTex *mtex;
+ Tex *tex;
+ float *co = NULL, *dx = NULL, *dy = NULL, fact, facm, stencilTin=1.0;
+ float texvec[3], dxt[3], dyt[3], tempvec[3];
+ int tex_nr, rgb= 0;
+
+ /* hier flag testen of er wel tex is */
+
+ la_col= la->org;
+
+ tex_nr= 0;
+
+ for(; tex_nr<6; tex_nr++) {
+
+ if(la->mtex[tex_nr]) {
+ mtex= la->mtex[tex_nr];
+
+ tex= mtex->tex;
+ if(tex==0) continue;
+
+ /* welke coords */
+ if(mtex->texco==TEXCO_OBJECT) {
+ ob= mtex->object;
+ if(ob) {
+ co= tempvec;
+ dx= dxt;
+ dy= dyt;
+ VECCOPY(tempvec, R.co);
+ MTC_Mat4MulVecfl(ob->imat, tempvec);
+ if(R.osatex) {
+ VECCOPY(dxt, O.dxco);
+ VECCOPY(dyt, O.dyco);
+ MTC_Mat4Mul3Vecfl(ob->imat, dxt);
+ MTC_Mat4Mul3Vecfl(ob->imat, dyt);
+ }
+ }
+ else {
+ co= R.co;
+ dx= O.dxco; dy= O.dyco;
+ }
+ }
+ else if(mtex->texco==TEXCO_GLOB) {
+ co= R.gl; dx= O.dxco; dy= O.dyco;
+ VECCOPY(R.gl, R.co);
+ MTC_Mat4MulVecfl(R.viewinv, R.gl);
+ }
+ else if(mtex->texco==TEXCO_VIEW) {
+
+ VECCOPY(tempvec, lavec);
+ MTC_Mat3MulVecfl(la->imat, tempvec);
+
+ tempvec[0]*= la->spottexfac;
+ tempvec[1]*= la->spottexfac;
+ co= tempvec;
+
+ dx= dxt; dy= dyt;
+ if(R.osatex) {
+ VECCOPY(dxt, O.dxlv);
+ VECCOPY(dyt, O.dylv);
+ /* need some matrix conversion here? la->imat is a [3][3] matrix!!! **/
+ MTC_Mat3MulVecfl(la->imat, dxt);
+ MTC_Mat3MulVecfl(la->imat, dyt);
+
+ VecMulf(dxt, la->spottexfac);
+ VecMulf(dyt, la->spottexfac);
+ }
+ }
+
+
+ /* placement */
+ if(mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]);
+ else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
+
+ if(mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]);
+ else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
+
+ if(mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]);
+ else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
+
+ if(R.osatex) {
+ if(mtex->projx) {
+ dxt[0]= mtex->size[0]*dx[mtex->projx-1];
+ dyt[0]= mtex->size[0]*dy[mtex->projx-1];
+ }
+ else dxt[0]= 0.0;
+ if(mtex->projy) {
+ dxt[1]= mtex->size[1]*dx[mtex->projy-1];
+ dyt[1]= mtex->size[1]*dy[mtex->projy-1];
+ }
+ else dxt[1]= 0.0;
+ if(mtex->projx) {
+ dxt[2]= mtex->size[2]*dx[mtex->projz-1];
+ dyt[2]= mtex->size[2]*dy[mtex->projz-1];
+ }
+ else dxt[2]= 0.0;
+ }
+
+ /* texture */
+ if(tex->type==TEX_IMAGE) {
+ do_2d_mapping(mtex, texvec, dxt, dyt);
+
+ if(mtex->mapto & MAP_NORM) {
+ /* de pointer bepaalt of er gebumpt wordt */
+ tex->nor= R.vn;
+ if(mtex->maptoneg & MAP_NORM) tex->norfac= -mtex->norfac;
+ else tex->norfac= mtex->norfac;
+ }
+ else tex->nor= 0;
+ }
+
+ rgb= multitex(tex, texvec, dxt, dyt);
+
+
+
+ /* texture uitgang */
+ if(rgb && (mtex->texflag & MTEX_RGBTOINT)) {
+ Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+ rgb= 0;
+ }
+ if(mtex->texflag & MTEX_NEGATIVE) {
+ if(rgb) {
+ Tr= 1.0-Tr;
+ Tg= 1.0-Tg;
+ Tb= 1.0-Tb;
+ }
+ else Tin= 1.0-Tin;
+ }
+ if(mtex->texflag & MTEX_STENCIL) {
+ if(rgb) {
+ fact= Ta;
+ Ta*= stencilTin;
+ stencilTin*= fact;
+ }
+ else {
+ fact= Tin;
+ Tin*= stencilTin;
+ stencilTin*= fact;
+ }
+ }
+ else {
+ if(rgb) Ta*= stencilTin;
+ else Tin*= stencilTin;
+ }
+
+ /* mapping */
+ if(mtex->mapto & LAMAP_COL) {
+
+ if(rgb==0) {
+ Tr= mtex->r;
+ Tg= mtex->g;
+ Tb= mtex->b;
+ }
+ else if(mtex->mapto & MAP_ALPHA) {
+ if(mtex->texflag & MTEX_ALPHAMIX) Tin= Ta;
+ else Tin= stencilTin;
+ }
+ else Tin= Ta;
+
+ Tr*= la->energy;
+ Tg*= la->energy;
+ Tb*= la->energy;
+
+ fact= Tin*mtex->colfac;
+ facm= 1.0-fact;
+ if(mtex->blendtype==MTEX_MUL) facm= 1.0-mtex->colfac;
+ if(mtex->blendtype==MTEX_SUB) fact= -fact;
+
+ if(mtex->blendtype==MTEX_BLEND) {
+ la->r= (fact*Tr + facm*la_col->r);
+ la->g= (fact*Tg + facm*la_col->g);
+ la->b= (fact*Tb + facm*la_col->b);
+ }
+ else if(mtex->blendtype==MTEX_MUL) {
+ la->r= (facm+fact*Tr)*la_col->r;
+ la->g= (facm+fact*Tg)*la_col->g;
+ la->b= (facm+fact*Tb)*la_col->b;
+ }
+ else {
+ la->r= (fact*Tr + la_col->r);
+ la->g= (fact*Tg + la_col->g);
+ la->b= (fact*Tb + la_col->b);
+ }
+ la_col= la; /* Is it just me or is this a useless statement? */
+ }
+
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void externtex(MTex *mtex, float *vec)
+{
+ Tex *tex;
+ float dxt[3], dyt[3], texvec[3];
+ int rgb;
+
+ tex= mtex->tex;
+ if(tex==0) return;
+
+ R.osatex= 0;
+ R.vlr= 0;
+
+ /* placement */
+ if(mtex->projx) texvec[0]= mtex->size[0]*(vec[mtex->projx-1]+mtex->ofs[0]);
+ else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
+
+ if(mtex->projy) texvec[1]= mtex->size[1]*(vec[mtex->projy-1]+mtex->ofs[1]);
+ else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
+
+ if(mtex->projz) texvec[2]= mtex->size[2]*(vec[mtex->projz-1]+mtex->ofs[2]);
+ else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
+
+ /* texture */
+ if(tex->type==TEX_IMAGE) {
+ do_2d_mapping(mtex, texvec, dxt, dyt);
+
+ if(mtex->mapto & MAP_NORM) {
+ /* de pointer bepaalt of er gebumpt wordt */
+ tex->nor= R.vn;
+ if(mtex->maptoneg & MAP_NORM) tex->norfac= -mtex->norfac;
+ else tex->norfac= mtex->norfac;
+ }
+ else tex->nor= 0;
+ }
+
+ rgb= multitex(tex, texvec, dxt, dyt);
+ if(rgb) {
+ Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+ }
+ else {
+ Tr= mtex->r;
+ Tg= mtex->g;
+ Tb= mtex->b;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void externtexcol(MTex *mtex, float *orco, char *col)
+{
+ int temp;
+ float b1;
+
+ if(mtex->tex==0) return;
+
+ externtex(mtex, orco);
+
+ b1= 1.0-Tin;
+
+ temp= 255*(Tin*Tr)+b1*col[0];
+ if(temp>255) col[0]= 255; else col[0]= temp;
+ temp= 255*(Tin*Tg)+b1*col[1];
+ if(temp>255) col[1]= 255; else col[1]= temp;
+ temp= 255*(Tin*Tb)+b1*col[2];
+ if(temp>255) col[2]= 255; else col[2]= temp;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void render_realtime_texture()
+{
+ static Tex tex;
+ static int firsttime= 1;
+ float texvec[2], dx[2], dy[2];
+
+ if(firsttime) {
+ default_tex(&tex);
+ tex.type= TEX_IMAGE;
+ firsttime= 0;
+ }
+
+ tex.ima = R.vlr->tface->tpage;
+ if(tex.ima) {
+
+ texvec[0]= 0.5+0.5*R.uv[0];
+ texvec[1]= 0.5+0.5*R.uv[1];
+ if(R.osatex) {
+ dx[0]= 0.5*O.dxuv[0];
+ dx[1]= 0.5*O.dxuv[1];
+ dy[0]= 0.5*O.dyuv[0];
+ dy[1]= 0.5*O.dyuv[1];
+ }
+
+ if(R.osatex) imagewraposa(&tex, texvec, dx, dy);
+ else imagewrap(&tex, texvec);
+
+ R.vcol[0]*= Tr;
+ R.vcol[1]*= Tg;
+ R.vcol[2]*= Tb;
+ }
+
+
+}
+
+/* eof */
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
new file mode 100644
index 00000000000..d0f3ba4cb1a
--- /dev/null
+++ b/source/blender/blenkernel/intern/world.c
@@ -0,0 +1,201 @@
+
+/* world.c MIX MODEL
+ *
+ * april 95
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <math.h>
+#include "MEM_guardedalloc.h"
+
+#include "DNA_world_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_scriptlink_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_camera_types.h"
+
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+
+#include "BKE_library.h"
+#include "BKE_world.h"
+#include "BKE_global.h"
+#include "BPY_extern.h"
+#include "BKE_main.h"
+
+
+void free_world(World *wrld)
+{
+ MTex *mtex;
+ int a;
+
+ BPY_free_scriptlink(&wrld->scriptlink);
+
+ for(a=0; a<8; a++) {
+ mtex= wrld->mtex[a];
+ if(mtex && mtex->tex) mtex->tex->id.us--;
+ if(mtex) MEM_freeN(mtex);
+ }
+ wrld->ipo= 0;
+}
+
+
+World *add_world(char *name)
+{
+ World *wrld;
+
+ wrld= alloc_libblock(&G.main->world, ID_WO, name);
+
+ wrld->horb= 0.6f;
+ wrld->skytype= WO_SKYBLEND;
+ wrld->exposure= 1.0f;
+ wrld->stardist= 15.0f;
+ wrld->starsize= 2.0f;
+ wrld->gravity= 9.8f;
+
+ return wrld;
+}
+
+World *copy_world(World *wrld)
+{
+ World *wrldn;
+ int a;
+
+ wrldn= copy_libblock(wrld);
+
+ for(a=0; a<8; a++) {
+ if(wrld->mtex[a]) {
+ wrldn->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial");
+ memcpy(wrldn->mtex[a], wrld->mtex[a], sizeof(MTex));
+ id_us_plus((ID *)wrldn->mtex[a]->tex);
+ }
+ }
+
+ BPY_copy_scriptlink(&wrld->scriptlink);
+
+ id_us_plus((ID *)wrldn->ipo);
+
+ return wrldn;
+}
+
+void make_local_world(World *wrld)
+{
+ Scene *sce;
+ World *wrldn;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(wrld->id.lib==0) return;
+ if(wrld->id.us==1) {
+ wrld->id.lib= 0;
+ wrld->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)wrld, 0);
+ return;
+ }
+
+ sce= G.main->scene.first;
+ while(sce) {
+ if(sce->world==wrld) {
+ if(sce->id.lib) lib= 1;
+ else local= 1;
+ }
+ sce= sce->id.next;
+ }
+
+ if(local && lib==0) {
+ wrld->id.lib= 0;
+ wrld->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)wrld, 0);
+ }
+ else if(local && lib) {
+ wrldn= copy_world(wrld);
+ wrldn->id.us= 0;
+
+ sce= G.main->scene.first;
+ while(sce) {
+ if(sce->world==wrld) {
+ if(sce->id.lib==0) {
+ sce->world= wrldn;
+ wrldn->id.us++;
+ wrld->id.us--;
+ }
+ }
+ sce= sce->id.next;
+ }
+ }
+}
+
+
+void init_render_world()
+{
+ int a;
+ char *cp;
+
+ if(G.scene->world) {
+ R.wrld= *(G.scene->world);
+
+ cp= (char *)&R.wrld.fastcol;
+
+ cp[0]= 255.0*R.wrld.horr;
+ cp[1]= 255.0*R.wrld.horg;
+ cp[2]= 255.0*R.wrld.horb;
+ cp[3]= 1;
+
+ VECCOPY(R.grvec, R.viewmat[2]);
+ Normalise(R.grvec);
+ Mat3CpyMat4(R.imat, R.viewinv);
+
+ for(a=0; a<6; a++) if(R.wrld.mtex[a] && R.wrld.mtex[a]->tex) R.wrld.skytype |= WO_SKYTEX;
+
+ if(G.scene->camera && G.scene->camera->type==OB_CAMERA) {
+ Camera *cam= G.scene->camera->data;
+ if(cam->type==CAM_ORTHO) {
+ /* dit is maar ongeveer */
+ R.wrld.miststa+= (float)fabs(R.viewmat[3][2]);
+ }
+ }
+ }
+ else {
+ memset(&R.wrld, 0, sizeof(World));
+ R.wrld.exposure= 1.0;
+ }
+}
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
new file mode 100644
index 00000000000..109553c816e
--- /dev/null
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -0,0 +1,147 @@
+/**
+ * Functions for writing avi-format files.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ */
+
+#include <string.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+
+#include "AVI_avi.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_global.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+static AviMovie *avi=NULL;
+static int sframe;
+
+void makeavistring (char *string)
+{
+ char txt[64];
+
+ if (string==0) return;
+
+ strcpy(string, G.scene->r.pic);
+ BLI_convertstringcode(string, G.sce, G.scene->r.cfra);
+
+ RE_make_existing_file(string);
+
+ if (strcasecmp(string + strlen(string) - 4, ".avi")) {
+ sprintf(txt, "%04d_%04d.avi", (G.scene->r.sfra) , (G.scene->r.efra) );
+ strcat(string, txt);
+ }
+}
+
+void start_avi(void)
+{
+ int x, y;
+ char name[256];
+ AviFormat format;
+ int quality, framerate;
+
+ makeavistring(name);
+
+ sframe = (G.scene->r.sfra);
+ x = R.rectx;
+ y = R.recty;
+
+ quality= R.r.quality;
+ framerate= R.r.frs_sec;
+
+ avi = MEM_mallocN (sizeof(AviMovie), "avimovie");
+
+ if (R.r.imtype != AVI_FORMAT_MJPEG) format = AVI_FORMAT_AVI_RGB;
+ else format = AVI_FORMAT_MJPEG;
+
+ if (AVI_open_compress (name, avi, 1, format) != AVI_ERROR_NONE) {
+ error("open movie");
+ MEM_freeN (avi);
+ avi = NULL;
+ return;
+ }
+
+ AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_WIDTH, &x);
+ AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_HEIGHT, &y);
+ AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_QUALITY, &quality);
+ AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_FRAMERATE, &framerate);
+
+ avi->interlace= 0;
+ avi->odd_fields= 0;
+/* avi->interlace= R.r.mode & R_FIELDS; */
+/* avi->odd_fields= (R.r.mode & R_ODDFIELD)?1:0; */
+
+ printf("Created avi: %s\n", name);
+}
+
+void append_avi(int frame)
+{
+ unsigned int *rt1, *rt2, *temp;
+ int y;
+
+ if (avi == NULL) {
+ G.afbreek = 1;
+ return;
+ }
+
+ /* note that libavi free's the buffer... stupid interface - zr */
+ temp = MEM_mallocN(R.rectx*R.recty*4, "append_avi buf");
+
+ rt1= temp;
+ rt2= R.rectot + (R.recty-1)*R.rectx;
+ for (y=0; y < R.recty; y++, rt1+= R.rectx, rt2-= R.rectx) {
+ memcpy (rt1, rt2, R.rectx*4);
+ }
+
+ IMB_convert_rgba_to_abgr(R.rectx*R.recty, temp);
+
+ AVI_write_frame (avi, (frame-sframe), AVI_FORMAT_RGB32,
+ temp, R.rectx*R.recty*4);
+ printf ("added frame %3d (frame %3d in avi): ", frame, frame-sframe);
+}
+
+void end_avi(void)
+{
+ if (avi == NULL) return;
+
+ AVI_close_compress (avi);
+ MEM_freeN (avi);
+ avi= NULL;
+}