diff options
author | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
---|---|---|
committer | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
commit | 420b91db29485df39fd6e724e782c449158811cb (patch) | |
tree | b471a94563af914d3ed3edd3e856d21cb1b69945 /indra/llprimitive |
Print done when done.
Diffstat (limited to 'indra/llprimitive')
-rw-r--r-- | indra/llprimitive/legacy_object_types.h | 59 | ||||
-rw-r--r-- | indra/llprimitive/llmaterialtable.cpp | 657 | ||||
-rw-r--r-- | indra/llprimitive/llmaterialtable.h | 116 | ||||
-rw-r--r-- | indra/llprimitive/llprimitive.cpp | 1749 | ||||
-rw-r--r-- | indra/llprimitive/llprimitive.h | 510 | ||||
-rw-r--r-- | indra/llprimitive/lltextureanim.cpp | 221 | ||||
-rw-r--r-- | indra/llprimitive/lltextureanim.h | 54 | ||||
-rw-r--r-- | indra/llprimitive/lltextureentry.cpp | 348 | ||||
-rw-r--r-- | indra/llprimitive/lltextureentry.h | 126 | ||||
-rw-r--r-- | indra/llprimitive/lltreeparams.cpp | 187 | ||||
-rw-r--r-- | indra/llprimitive/lltreeparams.h | 183 | ||||
-rw-r--r-- | indra/llprimitive/llvolumemessage.cpp | 534 | ||||
-rw-r--r-- | indra/llprimitive/llvolumemessage.h | 74 | ||||
-rw-r--r-- | indra/llprimitive/llvolumexml.cpp | 57 | ||||
-rw-r--r-- | indra/llprimitive/llvolumexml.h | 27 | ||||
-rw-r--r-- | indra/llprimitive/material_codes.h | 35 |
16 files changed, 4937 insertions, 0 deletions
diff --git a/indra/llprimitive/legacy_object_types.h b/indra/llprimitive/legacy_object_types.h new file mode 100644 index 0000000000..57ace87e89 --- /dev/null +++ b/indra/llprimitive/legacy_object_types.h @@ -0,0 +1,59 @@ +/** + * @file legacy_object_types.h + * @brief Byte codes for basic object and primitive types + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_LEGACY_OBJECT_TYPES_H +#define LL_LEGACY_OBJECT_TYPES_H + +const S8 PLAYER = 'c'; +//const S8 BASIC_SHOT = 's'; +//const S8 BIG_SHOT = 'S'; +//const S8 TREE_SHOT = 'g'; +//const S8 PHYSICAL_BALL = 'b'; + +const S8 TREE = 'T'; +const S8 TREE_NEW = 'R'; +//const S8 SPARK = 'p'; +//const S8 SMOKE = 'q'; +//const S8 BOX = 'x'; +//const S8 CYLINDER = 'y'; +//const S8 CONE = 'o'; +//const S8 SPHERE = 'h'; +//const S8 BIRD = 'r'; // ascii 114 +//const S8 ATOR = 'a'; +//const S8 ROCK = 'k'; + +const S8 GRASS = 'd'; +const S8 PART_SYS = 'P'; + +//const S8 ORACLE = 'O'; +//const S8 TEXTBUBBLE = 't'; // Text bubble to show communication +//const S8 DEMON = 'M'; // Maxwell's demon for scarfing legacy_object_types.h +//const S8 CUBE = 'f'; +//const S8 LSL_TEST = 'L'; +//const S8 PRISM = '1'; +//const S8 PYRAMID = '2'; +//const S8 TETRAHEDRON = '3'; +//const S8 HALF_CYLINDER = '4'; +//const S8 HALF_CONE = '5'; +//const S8 HALF_SPHERE = '6'; + +const S8 PRIMITIVE_VOLUME = 'v'; + +// Misc constants + +//const F32 AVATAR_RADIUS = 0.5f; +//const F32 SHOT_RADIUS = 0.05f; +//const F32 BIG_SHOT_RADIUS = 0.05f; +//const F32 TREE_SIZE = 5.f; +//const F32 BALL_SIZE = 4.f; + +//const F32 SHOT_VELOCITY = 100.f; +//const F32 GRENADE_BLAST_RADIUS = 5.f; + +#endif + diff --git a/indra/llprimitive/llmaterialtable.cpp b/indra/llprimitive/llmaterialtable.cpp new file mode 100644 index 0000000000..ebd6306284 --- /dev/null +++ b/indra/llprimitive/llmaterialtable.cpp @@ -0,0 +1,657 @@ +/** + * @file llmaterialtable.cpp + * @brief Table of material names and IDs for viewer + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "linden_common.h" + +#include "llmaterialtable.h" +#include "material_codes.h" +#include "sound_ids.h" +#include "imageids.h" + +LLMaterialTable LLMaterialTable::basic(1); + +F32 const LLMaterialTable::DEFAULT_FRICTION = 0.5f; +F32 const LLMaterialTable::DEFAULT_RESTITUTION = 0.4f; + +LLMaterialTable::LLMaterialTable() +{ +} + +LLMaterialTable::LLMaterialTable(U8 isBasic) +{ + initBasicTable(); +} + +LLMaterialTable::~LLMaterialTable() +{ + if (mCollisionSoundMatrix) + { + delete [] mCollisionSoundMatrix; + mCollisionSoundMatrix = NULL; + } + + if (mSlidingSoundMatrix) + { + delete [] mSlidingSoundMatrix; + mSlidingSoundMatrix = NULL; + } + + if (mRollingSoundMatrix) + { + delete [] mRollingSoundMatrix; + mRollingSoundMatrix = NULL; + } + + mMaterialInfoList.deleteAllData(); +} + +void LLMaterialTable::initBasicTable() +{ + add(LL_MCODE_STONE,"Stone", LL_DEFAULT_STONE_UUID); + add(LL_MCODE_METAL,"Metal", LL_DEFAULT_METAL_UUID); + add(LL_MCODE_GLASS,"Glass", LL_DEFAULT_GLASS_UUID); + add(LL_MCODE_WOOD,"Wood", LL_DEFAULT_WOOD_UUID); + add(LL_MCODE_FLESH,"Flesh", LL_DEFAULT_FLESH_UUID); + add(LL_MCODE_PLASTIC,"Plastic", LL_DEFAULT_PLASTIC_UUID); + add(LL_MCODE_RUBBER,"Rubber", LL_DEFAULT_RUBBER_UUID); + add(LL_MCODE_LIGHT,"Light", LL_DEFAULT_LIGHT_UUID); + + // specify densities for these materials. . . + // these were taken from http://www.mcelwee.net/html/densities_of_various_materials.html + + addDensity(LL_MCODE_STONE,30.f); + addDensity(LL_MCODE_METAL,50.f); + addDensity(LL_MCODE_GLASS,20.f); + addDensity(LL_MCODE_WOOD,10.f); + addDensity(LL_MCODE_FLESH,10.f); + addDensity(LL_MCODE_PLASTIC,5.f); + addDensity(LL_MCODE_RUBBER,0.5f); // + addDensity(LL_MCODE_LIGHT,20.f); // + + // add damage and energy values + addDamageAndEnergy(LL_MCODE_STONE, 1.f, 1.f, 1.f); // concrete + addDamageAndEnergy(LL_MCODE_METAL, 1.f, 1.f, 1.f); // steel + addDamageAndEnergy(LL_MCODE_GLASS, 1.f, 1.f, 1.f); // borosilicate glass + addDamageAndEnergy(LL_MCODE_WOOD, 1.f, 1.f, 1.f); // southern pine + addDamageAndEnergy(LL_MCODE_FLESH, 1.f, 1.f, 1.f); // saltwater + addDamageAndEnergy(LL_MCODE_PLASTIC, 1.f, 1.f, 1.f); // HDPE + addDamageAndEnergy(LL_MCODE_RUBBER, 1.f, 1.f, 1.f); // + addDamageAndEnergy(LL_MCODE_LIGHT, 1.f, 1.f, 1.f); // + + addFriction(LL_MCODE_STONE,0.8f); // concrete + addFriction(LL_MCODE_METAL,0.3f); // steel + addFriction(LL_MCODE_GLASS,0.2f); // borosilicate glass + addFriction(LL_MCODE_WOOD,0.6f); // southern pine + addFriction(LL_MCODE_FLESH,0.9f); // saltwater + addFriction(LL_MCODE_PLASTIC,0.4f); // HDPE + addFriction(LL_MCODE_RUBBER,0.9f); // + addFriction(LL_MCODE_LIGHT,0.2f); // + + addRestitution(LL_MCODE_STONE,0.4f); // concrete + addRestitution(LL_MCODE_METAL,0.4f); // steel + addRestitution(LL_MCODE_GLASS,0.7f); // borosilicate glass + addRestitution(LL_MCODE_WOOD,0.5f); // southern pine + addRestitution(LL_MCODE_FLESH,0.3f); // saltwater + addRestitution(LL_MCODE_PLASTIC,0.7f); // HDPE + addRestitution(LL_MCODE_RUBBER,0.9f); // + addRestitution(LL_MCODE_LIGHT,0.7f); // + + addShatterSound(LL_MCODE_STONE,LLUUID("ea296329-0f09-4993-af1b-e6784bab1dc9")); + addShatterSound(LL_MCODE_METAL,LLUUID("d1375446-1c4d-470b-9135-30132433b678")); + addShatterSound(LL_MCODE_GLASS,LLUUID("85cda060-b393-48e6-81c8-2cfdfb275351")); + addShatterSound(LL_MCODE_WOOD,LLUUID("6f00669f-15e0-4793-a63e-c03f62fee43a")); + addShatterSound(LL_MCODE_FLESH,LLUUID("2d8c6f51-149e-4e23-8413-93a379b42b67")); + addShatterSound(LL_MCODE_PLASTIC,LLUUID("d55c7f3c-e1c3-4ddc-9eff-9ef805d9190e")); + addShatterSound(LL_MCODE_RUBBER,LLUUID("212b6d1e-8d9c-4986-b3aa-f3c6df8d987d")); + addShatterSound(LL_MCODE_LIGHT,LLUUID("d55c7f3c-e1c3-4ddc-9eff-9ef805d9190e")); + + // CollisionSounds + mCollisionSoundMatrix = new LLUUID[LL_MCODE_END*LL_MCODE_END]; + if (mCollisionSoundMatrix) + { + addCollisionSound(LL_MCODE_STONE, LL_MCODE_STONE, SND_STONE_STONE); + addCollisionSound(LL_MCODE_STONE, LL_MCODE_METAL, SND_STONE_METAL); + addCollisionSound(LL_MCODE_STONE, LL_MCODE_GLASS, SND_STONE_GLASS); + addCollisionSound(LL_MCODE_STONE, LL_MCODE_WOOD, SND_STONE_WOOD); + addCollisionSound(LL_MCODE_STONE, LL_MCODE_FLESH, SND_STONE_FLESH); + addCollisionSound(LL_MCODE_STONE, LL_MCODE_PLASTIC, SND_STONE_PLASTIC); + addCollisionSound(LL_MCODE_STONE, LL_MCODE_RUBBER, SND_STONE_RUBBER); + addCollisionSound(LL_MCODE_STONE, LL_MCODE_LIGHT, SND_STONE_PLASTIC); + + addCollisionSound(LL_MCODE_METAL, LL_MCODE_METAL, SND_METAL_METAL); + addCollisionSound(LL_MCODE_METAL, LL_MCODE_GLASS, SND_METAL_GLASS); + addCollisionSound(LL_MCODE_METAL, LL_MCODE_WOOD, SND_METAL_WOOD); + addCollisionSound(LL_MCODE_METAL, LL_MCODE_FLESH, SND_METAL_FLESH); + addCollisionSound(LL_MCODE_METAL, LL_MCODE_PLASTIC, SND_METAL_PLASTIC); + addCollisionSound(LL_MCODE_METAL, LL_MCODE_LIGHT, SND_METAL_PLASTIC); + addCollisionSound(LL_MCODE_METAL, LL_MCODE_RUBBER, SND_METAL_RUBBER); + + addCollisionSound(LL_MCODE_GLASS, LL_MCODE_GLASS, SND_GLASS_GLASS); + addCollisionSound(LL_MCODE_GLASS, LL_MCODE_WOOD, SND_GLASS_WOOD); + addCollisionSound(LL_MCODE_GLASS, LL_MCODE_FLESH, SND_GLASS_FLESH); + addCollisionSound(LL_MCODE_GLASS, LL_MCODE_PLASTIC, SND_GLASS_PLASTIC); + addCollisionSound(LL_MCODE_GLASS, LL_MCODE_RUBBER, SND_GLASS_RUBBER); + addCollisionSound(LL_MCODE_GLASS, LL_MCODE_LIGHT, SND_GLASS_PLASTIC); + + addCollisionSound(LL_MCODE_WOOD, LL_MCODE_WOOD, SND_WOOD_WOOD); + addCollisionSound(LL_MCODE_WOOD, LL_MCODE_FLESH, SND_WOOD_FLESH); + addCollisionSound(LL_MCODE_WOOD, LL_MCODE_PLASTIC, SND_WOOD_PLASTIC); + addCollisionSound(LL_MCODE_WOOD, LL_MCODE_RUBBER, SND_WOOD_RUBBER); + addCollisionSound(LL_MCODE_WOOD, LL_MCODE_LIGHT, SND_WOOD_PLASTIC); + + addCollisionSound(LL_MCODE_FLESH, LL_MCODE_FLESH, SND_FLESH_FLESH); + addCollisionSound(LL_MCODE_FLESH, LL_MCODE_PLASTIC, SND_FLESH_PLASTIC); + addCollisionSound(LL_MCODE_FLESH, LL_MCODE_RUBBER, SND_FLESH_RUBBER); + addCollisionSound(LL_MCODE_FLESH, LL_MCODE_LIGHT, SND_FLESH_PLASTIC); + + addCollisionSound(LL_MCODE_RUBBER, LL_MCODE_RUBBER, SND_RUBBER_RUBBER); + addCollisionSound(LL_MCODE_RUBBER, LL_MCODE_PLASTIC, SND_RUBBER_PLASTIC); + addCollisionSound(LL_MCODE_RUBBER, LL_MCODE_LIGHT, SND_RUBBER_PLASTIC); + + addCollisionSound(LL_MCODE_PLASTIC, LL_MCODE_PLASTIC, SND_PLASTIC_PLASTIC); + addCollisionSound(LL_MCODE_PLASTIC, LL_MCODE_LIGHT, SND_PLASTIC_PLASTIC); + + addCollisionSound(LL_MCODE_LIGHT, LL_MCODE_LIGHT, SND_PLASTIC_PLASTIC); + } + + // Sliding Sounds + mSlidingSoundMatrix = new LLUUID[LL_MCODE_END*LL_MCODE_END]; + if (mSlidingSoundMatrix) + { + addSlidingSound(LL_MCODE_STONE, LL_MCODE_STONE, SND_SLIDE_STONE_STONE); + addSlidingSound(LL_MCODE_STONE, LL_MCODE_METAL, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_STONE, LL_MCODE_GLASS, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_STONE, LL_MCODE_WOOD, SND_SLIDE_STONE_WOOD); + addSlidingSound(LL_MCODE_STONE, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_STONE, LL_MCODE_PLASTIC, SND_SLIDE_STONE_PLASTIC); + addSlidingSound(LL_MCODE_STONE, LL_MCODE_RUBBER, SND_SLIDE_STONE_RUBBER); + addSlidingSound(LL_MCODE_STONE, LL_MCODE_LIGHT, SND_SLIDE_STONE_PLASTIC); + + addSlidingSound(LL_MCODE_METAL, LL_MCODE_METAL, SND_SLIDE_METAL_METAL); + addSlidingSound(LL_MCODE_METAL, LL_MCODE_GLASS, SND_SLIDE_METAL_GLASS); + addSlidingSound(LL_MCODE_METAL, LL_MCODE_WOOD, SND_SLIDE_METAL_WOOD); + addSlidingSound(LL_MCODE_METAL, LL_MCODE_FLESH, SND_SLIDE_METAL_FLESH); + addSlidingSound(LL_MCODE_METAL, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_METAL, LL_MCODE_RUBBER, SND_SLIDE_METAL_RUBBER); + addSlidingSound(LL_MCODE_METAL, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); + + addSlidingSound(LL_MCODE_GLASS, LL_MCODE_GLASS, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_GLASS, LL_MCODE_WOOD, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_GLASS, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_GLASS, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_GLASS, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_GLASS, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); + + addSlidingSound(LL_MCODE_WOOD, LL_MCODE_WOOD, SND_SLIDE_WOOD_WOOD); + addSlidingSound(LL_MCODE_WOOD, LL_MCODE_FLESH, SND_SLIDE_WOOD_FLESH); + addSlidingSound(LL_MCODE_WOOD, LL_MCODE_PLASTIC, SND_SLIDE_WOOD_PLASTIC); + addSlidingSound(LL_MCODE_WOOD, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_WOOD, LL_MCODE_LIGHT, SND_SLIDE_WOOD_PLASTIC); + + addSlidingSound(LL_MCODE_FLESH, LL_MCODE_FLESH, SND_SLIDE_FLESH_FLESH); + addSlidingSound(LL_MCODE_FLESH, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_FLESH, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_FLESH, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); + + addSlidingSound(LL_MCODE_RUBBER, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_RUBBER, LL_MCODE_PLASTIC, SND_SLIDE_RUBBER_PLASTIC); + addSlidingSound(LL_MCODE_RUBBER, LL_MCODE_LIGHT, SND_SLIDE_RUBBER_PLASTIC); + + addSlidingSound(LL_MCODE_PLASTIC, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); + addSlidingSound(LL_MCODE_PLASTIC, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); + + addSlidingSound(LL_MCODE_LIGHT, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); + } + + // Rolling Sounds + mRollingSoundMatrix = new LLUUID[LL_MCODE_END*LL_MCODE_END]; + if (mRollingSoundMatrix) + { + addRollingSound(LL_MCODE_STONE, LL_MCODE_STONE, SND_ROLL_STONE_STONE); + addRollingSound(LL_MCODE_STONE, LL_MCODE_METAL, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_STONE, LL_MCODE_GLASS, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_STONE, LL_MCODE_WOOD, SND_ROLL_STONE_WOOD); + addRollingSound(LL_MCODE_STONE, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_STONE, LL_MCODE_PLASTIC, SND_ROLL_STONE_PLASTIC); + addRollingSound(LL_MCODE_STONE, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_STONE, LL_MCODE_LIGHT, SND_ROLL_STONE_PLASTIC); + + addRollingSound(LL_MCODE_METAL, LL_MCODE_METAL, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_METAL, LL_MCODE_GLASS, SND_ROLL_METAL_GLASS); + addRollingSound(LL_MCODE_METAL, LL_MCODE_WOOD, SND_ROLL_METAL_WOOD); + addRollingSound(LL_MCODE_METAL, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_METAL, LL_MCODE_PLASTIC, SND_ROLL_METAL_WOOD); + addRollingSound(LL_MCODE_METAL, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_METAL, LL_MCODE_LIGHT, SND_ROLL_METAL_WOOD); + + addRollingSound(LL_MCODE_GLASS, LL_MCODE_GLASS, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_GLASS, LL_MCODE_WOOD, SND_ROLL_GLASS_WOOD); + addRollingSound(LL_MCODE_GLASS, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_GLASS, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_GLASS, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_GLASS, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); + + addRollingSound(LL_MCODE_WOOD, LL_MCODE_WOOD, SND_ROLL_WOOD_WOOD); + addRollingSound(LL_MCODE_WOOD, LL_MCODE_FLESH, SND_ROLL_WOOD_FLESH); + addRollingSound(LL_MCODE_WOOD, LL_MCODE_PLASTIC, SND_ROLL_WOOD_PLASTIC); + addRollingSound(LL_MCODE_WOOD, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_WOOD, LL_MCODE_LIGHT, SND_ROLL_WOOD_PLASTIC); + + addRollingSound(LL_MCODE_FLESH, LL_MCODE_FLESH, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_FLESH, LL_MCODE_PLASTIC, SND_ROLL_FLESH_PLASTIC); + addRollingSound(LL_MCODE_FLESH, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_FLESH, LL_MCODE_LIGHT, SND_ROLL_FLESH_PLASTIC); + + addRollingSound(LL_MCODE_RUBBER, LL_MCODE_RUBBER, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_RUBBER, LL_MCODE_PLASTIC, SND_SLIDE_STONE_STONE_01); + addRollingSound(LL_MCODE_RUBBER, LL_MCODE_LIGHT, SND_SLIDE_STONE_STONE_01); + + addRollingSound(LL_MCODE_PLASTIC, LL_MCODE_PLASTIC, SND_ROLL_PLASTIC_PLASTIC); + addRollingSound(LL_MCODE_PLASTIC, LL_MCODE_LIGHT, SND_ROLL_PLASTIC_PLASTIC); + + addRollingSound(LL_MCODE_LIGHT, LL_MCODE_LIGHT, SND_ROLL_PLASTIC_PLASTIC); + } +} + +BOOL LLMaterialTable::add(U8 mcode, char* name, const LLUUID &uuid) +{ + LLMaterialInfo *infop; + + infop = new LLMaterialInfo(mcode,name,uuid); + if (!infop) return FALSE; + + // Add at the end so the order in menus matches the order in this + // file. JNC 11.30.01 + mMaterialInfoList.addDataAtEnd(infop); + + return TRUE; +} + +BOOL LLMaterialTable::addCollisionSound(U8 mcode, U8 mcode2, const LLUUID &uuid) +{ + if (mCollisionSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) + { + mCollisionSoundMatrix[mcode * LL_MCODE_END + mcode2] = uuid; + if (mcode != mcode2) + { + mCollisionSoundMatrix[mcode2 * LL_MCODE_END + mcode] = uuid; + } + } + return TRUE; +} + +BOOL LLMaterialTable::addSlidingSound(U8 mcode, U8 mcode2, const LLUUID &uuid) +{ + if (mSlidingSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) + { + mSlidingSoundMatrix[mcode * LL_MCODE_END + mcode2] = uuid; + if (mcode != mcode2) + { + mSlidingSoundMatrix[mcode2 * LL_MCODE_END + mcode] = uuid; + } + } + return TRUE; +} + +BOOL LLMaterialTable::addRollingSound(U8 mcode, U8 mcode2, const LLUUID &uuid) +{ + if (mRollingSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) + { + mRollingSoundMatrix[mcode * LL_MCODE_END + mcode2] = uuid; + if (mcode != mcode2) + { + mRollingSoundMatrix[mcode2 * LL_MCODE_END + mcode] = uuid; + } + } + return TRUE; +} + +BOOL LLMaterialTable::addShatterSound(U8 mcode, const LLUUID &uuid) +{ + LLMaterialInfo *infop; + + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (mcode == infop->mMCode) + { + infop->mShatterSoundID = uuid; + return TRUE; + } + } + + return FALSE; +} + +BOOL LLMaterialTable::addDensity(U8 mcode, const F32 &density) +{ + LLMaterialInfo *infop; + + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (mcode == infop->mMCode) + { + infop->mDensity = density; + return TRUE; + } + } + + return FALSE; +} + +BOOL LLMaterialTable::addRestitution(U8 mcode, const F32 &restitution) +{ + LLMaterialInfo *infop; + + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (mcode == infop->mMCode) + { + infop->mRestitution = restitution; + return TRUE; + } + } + + return FALSE; +} + +BOOL LLMaterialTable::addFriction(U8 mcode, const F32 &friction) +{ + LLMaterialInfo *infop; + + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (mcode == infop->mMCode) + { + infop->mFriction = friction; + return TRUE; + } + } + + return FALSE; +} + +BOOL LLMaterialTable::addDamageAndEnergy(U8 mcode, const F32 &hp_mod, const F32 &damage_mod, const F32 &ep_mod) +{ + LLMaterialInfo *infop; + + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (mcode == infop->mMCode) + { + infop->mHPModifier = hp_mod; + infop->mDamageModifier = damage_mod; + infop->mEPModifier = ep_mod; + return TRUE; + } + } + + return FALSE; +} + +LLUUID LLMaterialTable::getDefaultTextureID(char* name) +{ + LLMaterialInfo *infop; + + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (!strcmp(name, infop->mName)) + { + return infop->mDefaultTextureID; + } + } + + return LLUUID::null; +} + + +LLUUID LLMaterialTable::getDefaultTextureID(U8 mcode) +{ + LLMaterialInfo *infop; + + mcode &= LL_MCODE_MASK; + + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (mcode == infop->mMCode) + { + return infop->mDefaultTextureID; + } + } + + return LLUUID::null; +} + + +U8 LLMaterialTable::getMCode(const char* name) +{ + LLMaterialInfo *infop; + + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (!strcmp(name, infop->mName)) + { + return infop->mMCode; + } + } + + return 0; +} + + +char* LLMaterialTable::getName(U8 mcode) +{ + LLMaterialInfo *infop; + + mcode &= LL_MCODE_MASK; + + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (mcode == infop->mMCode) + { + return infop->mName; + } + } + + return NULL; +} + + +LLUUID LLMaterialTable::getCollisionSoundUUID(U8 mcode, U8 mcode2) +{ + mcode &= LL_MCODE_MASK; + mcode2 &= LL_MCODE_MASK; + + //llinfos << "code 1: " << ((U32) mcode) << " code 2:" << ((U32) mcode2) << llendl; + if (mCollisionSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) + { + return(mCollisionSoundMatrix[mcode * LL_MCODE_END + mcode2]); + } + else + { + //llinfos << "Null Sound" << llendl; + return(SND_NULL); + } +} + +LLUUID LLMaterialTable::getSlidingSoundUUID(U8 mcode, U8 mcode2) +{ + mcode &= LL_MCODE_MASK; + mcode2 &= LL_MCODE_MASK; + + if (mSlidingSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) + { + return(mSlidingSoundMatrix[mcode * LL_MCODE_END + mcode2]); + } + else + { + return(SND_NULL); + } +} + +LLUUID LLMaterialTable::getRollingSoundUUID(U8 mcode, U8 mcode2) +{ + mcode &= LL_MCODE_MASK; + mcode2 &= LL_MCODE_MASK; + + if (mRollingSoundMatrix && (mcode < LL_MCODE_END) && (mcode2 < LL_MCODE_END)) + { + return(mRollingSoundMatrix[mcode * LL_MCODE_END + mcode2]); + } + else + { + return(SND_NULL); + } +} + +LLUUID LLMaterialTable::getGroundCollisionSoundUUID(U8 mcode) +{ + // Create material appropriate sounds for collisions with the ground + // For now, simply return a single sound for all materials + return SND_STONE_DIRT_02; +} + +LLUUID LLMaterialTable::getGroundSlidingSoundUUID(U8 mcode) +{ + // Create material-specific sound for sliding on ground + // For now, just return a single sound + return SND_SLIDE_STONE_STONE_01; +} + +LLUUID LLMaterialTable::getGroundRollingSoundUUID(U8 mcode) +{ + // Create material-specific sound for rolling on ground + // For now, just return a single sound + return SND_SLIDE_STONE_STONE_01; +} + +LLUUID LLMaterialTable::getCollisionParticleUUID(U8 mcode, U8 mcode2) +{ + // Returns an appropriate UUID to use as sprite at collision betweeen objects + // For now, just return a single image + return IMG_SHOT; +} + +LLUUID LLMaterialTable::getGroundCollisionParticleUUID(U8 mcode) +{ + // Returns an appropriate + // For now, just return a single sound + return IMG_SMOKE_POOF; +} + + +F32 LLMaterialTable::getDensity(U8 mcode) +{ + LLMaterialInfo *infop; + + mcode &= LL_MCODE_MASK; + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (mcode == infop->mMCode) + { + return infop->mDensity; + } + } + + return 0.f; +} + +F32 LLMaterialTable::getRestitution(U8 mcode) +{ + LLMaterialInfo *infop; + + mcode &= LL_MCODE_MASK; + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (mcode == infop->mMCode) + { + return infop->mRestitution; + } + } + + return LLMaterialTable::DEFAULT_RESTITUTION; +} + +F32 LLMaterialTable::getFriction(U8 mcode) +{ + LLMaterialInfo *infop; + + mcode &= LL_MCODE_MASK; + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (mcode == infop->mMCode) + { + return infop->mFriction; + } + } + + return LLMaterialTable::DEFAULT_FRICTION; +} + +F32 LLMaterialTable::getHPMod(U8 mcode) +{ + LLMaterialInfo *infop; + + mcode &= LL_MCODE_MASK; + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (mcode == infop->mMCode) + { + return infop->mHPModifier; + } + } + + return 1.f; +} + +F32 LLMaterialTable::getDamageMod(U8 mcode) +{ + LLMaterialInfo *infop; + + mcode &= LL_MCODE_MASK; + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (mcode == infop->mMCode) + { + return infop->mDamageModifier; + } + } + + return 1.f; +} + +F32 LLMaterialTable::getEPMod(U8 mcode) +{ + LLMaterialInfo *infop; + + mcode &= LL_MCODE_MASK; + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (mcode == infop->mMCode) + { + return infop->mEPModifier; + } + } + + return 1.f; +} + +LLUUID LLMaterialTable::getShatterSoundUUID(U8 mcode) +{ + LLMaterialInfo *infop; + + mcode &= LL_MCODE_MASK; + for (infop = mMaterialInfoList.getFirstData(); infop != NULL; infop = mMaterialInfoList.getNextData() ) + { + if (mcode == infop->mMCode) + { + return infop->mShatterSoundID; + } + } + + return SND_NULL; +} diff --git a/indra/llprimitive/llmaterialtable.h b/indra/llprimitive/llmaterialtable.h new file mode 100644 index 0000000000..7146be54cf --- /dev/null +++ b/indra/llprimitive/llmaterialtable.h @@ -0,0 +1,116 @@ +/** + * @file llmaterialtable.h + * @brief Table of material information for the viewer UI + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_LLMATERIALTABLE_H +#define LL_LLMATERIALTABLE_H + +#include "lluuid.h" +#include "linked_lists.h" +#include "llstring.h" + +const U32 LLMATERIAL_INFO_NAME_LENGTH = 256; + +class LLMaterialInfo +{ +public: + U8 mMCode; + char mName[LLMATERIAL_INFO_NAME_LENGTH]; + LLUUID mDefaultTextureID; + LLUUID mShatterSoundID; + F32 mDensity; // kg/m^3 + F32 mFriction; + F32 mRestitution; + + // damage and energy constants + F32 mHPModifier; // modifier on mass based HP total + F32 mDamageModifier; // modifier on KE based damage + F32 mEPModifier; // modifier on mass based EP total + + LLMaterialInfo(U8 mcode, char* name, const LLUUID &uuid) + { + init(mcode,name,uuid); + }; + + void init(U8 mcode, char* name, const LLUUID &uuid) + { + mName[0] = 0; + mDensity = 1000.f; // default to 1000.0 (water) + mHPModifier = 1.f; + mDamageModifier = 1.f; + mEPModifier = 1.f; + + mMCode = mcode; + if (name) + { + LLString::copy(mName,name,LLMATERIAL_INFO_NAME_LENGTH); + } + mDefaultTextureID = uuid; + }; + + ~LLMaterialInfo() + { + }; + +}; + +class LLMaterialTable +{ +public: + LLLinkedList<LLMaterialInfo> mMaterialInfoList; + LLUUID *mCollisionSoundMatrix; + LLUUID *mSlidingSoundMatrix; + LLUUID *mRollingSoundMatrix; + + static const F32 DEFAULT_FRICTION; + static const F32 DEFAULT_RESTITUTION; + +public: + LLMaterialTable(); + LLMaterialTable(U8); // cheat with an overloaded constructor to build our basic table + ~LLMaterialTable(); + + void initBasicTable(); + + BOOL add(U8 mcode, char* name, const LLUUID &uuid); + BOOL addCollisionSound(U8 mcode, U8 mcode2, const LLUUID &uuid); + BOOL addSlidingSound(U8 mcode, U8 mcode2, const LLUUID &uuid); + BOOL addRollingSound(U8 mcode, U8 mcode2, const LLUUID &uuid); + BOOL addShatterSound(U8 mcode, const LLUUID &uuid); + BOOL addDensity(U8 mcode, const F32 &density); + BOOL addFriction(U8 mcode, const F32 &friction); + BOOL addRestitution(U8 mcode, const F32 &restitution); + BOOL addDamageAndEnergy(U8 mcode, const F32 &hp_mod, const F32 &damage_mod, const F32 &ep_mod); + + LLUUID getDefaultTextureID(char* name); // LLUUID::null if not found + LLUUID getDefaultTextureID(U8 mcode); // LLUUID::null if not found + U8 getMCode(const char* name); // 0 if not found + char* getName(U8 mcode); + + F32 getDensity(U8 mcode); // kg/m^3, 0 if not found + F32 getFriction(U8 mcode); // havok values + F32 getRestitution(U8 mcode); // havok values + F32 getHPMod(U8 mcode); + F32 getDamageMod(U8 mcode); + F32 getEPMod(U8 mcode); + + LLUUID getCollisionSoundUUID(U8 mcode, U8 mcode2); + LLUUID getSlidingSoundUUID(U8 mcode, U8 mcode2); + LLUUID getRollingSoundUUID(U8 mcode, U8 mcode2); + LLUUID getShatterSoundUUID(U8 mcode); // LLUUID::null if not found + + LLUUID getGroundCollisionSoundUUID(U8 mcode); + LLUUID getGroundSlidingSoundUUID(U8 mcode); + LLUUID getGroundRollingSoundUUID(U8 mcode); + LLUUID getCollisionParticleUUID(U8 mcode, U8 mcode2); + LLUUID getGroundCollisionParticleUUID(U8 mcode); + + static LLMaterialTable basic; +}; + +#endif + diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp new file mode 100644 index 0000000000..fa8010eb6b --- /dev/null +++ b/indra/llprimitive/llprimitive.cpp @@ -0,0 +1,1749 @@ +/** + * @file llprimitive.cpp + * @brief LLPrimitive base class + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "linden_common.h" + +#include "material_codes.h" +#include "llerror.h" +#include "message.h" +#include "llprimitive.h" +#include "llvolume.h" +#include "legacy_object_types.h" +#include "v4coloru.h" +#include "llvolumemgr.h" +#include "llstring.h" +#include "lldatapacker.h" + +/** + * exported constants + */ + +const F32 OBJECT_CUT_MIN = 0.f; +const F32 OBJECT_CUT_MAX = 1.f; +const F32 OBJECT_CUT_INC = 0.05f; +const F32 OBJECT_MIN_CUT_INC = 0.02f; +const F32 OBJECT_ROTATION_PRECISION = 0.05f; + +const F32 OBJECT_TWIST_MIN = -360.f; +const F32 OBJECT_TWIST_MAX = 360.f; +const F32 OBJECT_TWIST_INC = 18.f; + +// This is used for linear paths, +// since twist is used in a slightly different manner. +const F32 OBJECT_TWIST_LINEAR_MIN = -180.f; +const F32 OBJECT_TWIST_LINEAR_MAX = 180.f; +const F32 OBJECT_TWIST_LINEAR_INC = 9.f; + +const F32 OBJECT_MIN_HOLE_SIZE = 0.05f; +const F32 OBJECT_MAX_HOLE_SIZE_X = 1.0f; +const F32 OBJECT_MAX_HOLE_SIZE_Y = 0.5f; + +// Revolutions parameters. +const F32 OBJECT_REV_MIN = 1.0f; +const F32 OBJECT_REV_MAX = 4.0f; +const F32 OBJECT_REV_INC = 0.1f; + +// lights +const F32 LIGHT_MIN_RADIUS = 0.0f; +const F32 LIGHT_DEFAULT_RADIUS = 5.0f; +const F32 LIGHT_MAX_RADIUS = 20.0f; +const F32 LIGHT_MIN_FALLOFF = 0.0f; +const F32 LIGHT_DEFAULT_FALLOFF = 1.0f; +const F32 LIGHT_MAX_FALLOFF = 2.0f; +const F32 LIGHT_MIN_CUTOFF = 0.0f; +const F32 LIGHT_DEFAULT_CUTOFF = 0.0f; +const F32 LIGHT_MAX_CUTOFF = 180.f; + +// "Tension" => [0,10], increments of 0.1 +const F32 FLEXIBLE_OBJECT_MIN_TENSION = 0.0f; +const F32 FLEXIBLE_OBJECT_DEFAULT_TENSION = 1.0f; +const F32 FLEXIBLE_OBJECT_MAX_TENSION = 10.0f; + +// "Drag" => [0,10], increments of 0.1 +const F32 FLEXIBLE_OBJECT_MIN_AIR_FRICTION = 0.0f; +const F32 FLEXIBLE_OBJECT_DEFAULT_AIR_FRICTION = 2.0f; +const F32 FLEXIBLE_OBJECT_MAX_AIR_FRICTION = 10.0f; + +// "Gravity" = [-10,10], increments of 0.1 +const F32 FLEXIBLE_OBJECT_MIN_GRAVITY = -10.0f; +const F32 FLEXIBLE_OBJECT_DEFAULT_GRAVITY = 0.3f; +const F32 FLEXIBLE_OBJECT_MAX_GRAVITY = 10.0f; + +// "Wind" = [0,10], increments of 0.1 +const F32 FLEXIBLE_OBJECT_MIN_WIND_SENSITIVITY = 0.0f; +const F32 FLEXIBLE_OBJECT_DEFAULT_WIND_SENSITIVITY = 0.0f; +const F32 FLEXIBLE_OBJECT_MAX_WIND_SENSITIVITY = 10.0f; + +// I'll explain later... +const F32 FLEXIBLE_OBJECT_MAX_INTERNAL_TENSION_FORCE = 0.99f; + +const F32 FLEXIBLE_OBJECT_DEFAULT_LENGTH = 1.0f; +const BOOL FLEXIBLE_OBJECT_DEFAULT_USING_COLLISION_SPHERE = FALSE; +const BOOL FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE = FALSE; + + +//=============================================================== +LLPrimitive::LLPrimitive() +{ + mPrimitiveCode = 0; + + mMaterial = LL_MCODE_STONE; + mVolumep = NULL; + + mChanged = UNCHANGED; + + mPosition.setVec(0.f,0.f,0.f); + mVelocity.setVec(0.f,0.f,0.f); + mAcceleration.setVec(0.f,0.f,0.f); + + mRotation.loadIdentity(); + mAngularVelocity.setVec(0.f,0.f,0.f); + + mScale.setVec(1.f,1.f,1.f); + + mNumTEs = 0; + mTextureList = NULL; +} + +//=============================================================== +LLPrimitive::~LLPrimitive() +{ + if (mTextureList) + { + delete [] mTextureList; + mTextureList = NULL; + } + + // Cleanup handled by volume manager + if (mVolumep) + { + gVolumeMgr->cleanupVolume(mVolumep); + } + mVolumep = NULL; +} + +//=============================================================== +// static +LLPrimitive *LLPrimitive::createPrimitive(LLPCode p_code) +{ + LLPrimitive *retval = new LLPrimitive(); + + if (retval) + { + retval->init(p_code); + } + else + { + llerrs << "primitive allocation failed" << llendl; + } + + return retval; +} + +//=============================================================== +void LLPrimitive::init(LLPCode p_code) +{ + if (mNumTEs) + { + if (mTextureList) + { + delete [] mTextureList; + } + mTextureList = new LLTextureEntry[mNumTEs]; + } + + mPrimitiveCode = p_code; +} + +void LLPrimitive::setPCode(const U8 p_code) +{ + mPrimitiveCode = p_code; +} + +//=============================================================== +const LLTextureEntry * LLPrimitive::getTE(const U8 te_num) const +{ + // if we're asking for a non-existent face, return null + if (mNumTEs && (te_num< mNumTEs)) + { + return(&mTextureList[te_num]); + } + else + { + return(NULL); + } +} + +//=============================================================== +void LLPrimitive::setNumTEs(const U8 num_tes) +{ + if (num_tes == mNumTEs) + { + return; + } + + // Right now, we don't try and preserve entries when the number of faces + // changes. + + if (num_tes) + { + LLTextureEntry *new_tes; + new_tes = new LLTextureEntry[num_tes]; + U32 i; + for (i = 0; i < num_tes; i++) + { + if (i < mNumTEs) + { + new_tes[i] = mTextureList[i]; + } + else if (mNumTEs) + { + new_tes[i] = mTextureList[mNumTEs - 1]; + } + else + { + new_tes[i] = LLTextureEntry(); + } + } + delete[] mTextureList; + mTextureList = new_tes; + } + else + { + delete[] mTextureList; + mTextureList = NULL; + } + + + mNumTEs = num_tes; +} + +//=============================================================== +void LLPrimitive::setAllTETextures(const LLUUID &tex_id) +{ + U8 i; + + for (i = 0; i < mNumTEs; i++) + { + mTextureList[i].setID(tex_id); + } +} + +//=============================================================== +void LLPrimitive::setTE(const U8 index, const LLTextureEntry &te) +{ + mTextureList[index] = te; +} + +S32 LLPrimitive::setTETexture(const U8 te, const LLUUID &tex_id) +{ + // if we're asking for a non-existent face, return null + if (te >= mNumTEs) + { + llwarns << "setting non-existent te " << te << llendl + return 0; + } + + return mTextureList[te].setID(tex_id); +} + +S32 LLPrimitive::setTEColor(const U8 te, const LLColor4 &color) +{ + // if we're asking for a non-existent face, return null + if (te >= mNumTEs) + { + llwarns << "setting non-existent te " << te << llendl + return 0; + } + + return mTextureList[te].setColor(color); +} + +S32 LLPrimitive::setTEColor(const U8 te, const LLColor3 &color) +{ + // if we're asking for a non-existent face, return null + if (te >= mNumTEs) + { + llwarns << "setting non-existent te " << te << llendl + return 0; + } + + return mTextureList[te].setColor(color); +} + +S32 LLPrimitive::setTEAlpha(const U8 te, const F32 alpha) +{ + // if we're asking for a non-existent face, return null + if (te >= mNumTEs) + { + llwarns << "setting non-existent te " << te << llendl + return 0; + } + + return mTextureList[te].setAlpha(alpha); +} + +//=============================================================== +S32 LLPrimitive::setTEScale(const U8 te, const F32 s, const F32 t) +{ + // if we're asking for a non-existent face, return null + if (te >= mNumTEs) + { + llwarns << "Setting nonexistent face" << llendl; + return 0; + } + + return mTextureList[te].setScale(s,t); +} + + +// BUG: slow - done this way because texture entries have some +// voodoo related to texture coords +S32 LLPrimitive::setTEScaleS(const U8 te, const F32 s) +{ + if (te >= mNumTEs) + { + llwarns << "Setting nonexistent face" << llendl; + return 0; + } + + F32 ignore, t; + mTextureList[te].getScale(&ignore, &t); + return mTextureList[te].setScale(s,t); +} + + +// BUG: slow - done this way because texture entries have some +// voodoo related to texture coords +S32 LLPrimitive::setTEScaleT(const U8 te, const F32 t) +{ + if (te >= mNumTEs) + { + llwarns << "Setting nonexistent face" << llendl; + return 0; + } + + F32 s, ignore; + mTextureList[te].getScale(&s, &ignore); + return mTextureList[te].setScale(s,t); +} + + +//=============================================================== +S32 LLPrimitive::setTEOffset(const U8 te, const F32 s, const F32 t) +{ + // if we're asking for a non-existent face, return null + if (te >= mNumTEs) + { + llwarns << "Setting nonexistent face" << llendl; + return 0; + } + + return mTextureList[te].setOffset(s,t); +} + + +// BUG: slow - done this way because texture entries have some +// voodoo related to texture coords +S32 LLPrimitive::setTEOffsetS(const U8 te, const F32 s) +{ + if (te >= mNumTEs) + { + llwarns << "Setting nonexistent face" << llendl; + return 0; + } + + F32 ignore, t; + mTextureList[te].getOffset(&ignore, &t); + return mTextureList[te].setOffset(s,t); +} + + +// BUG: slow - done this way because texture entries have some +// voodoo related to texture coords +S32 LLPrimitive::setTEOffsetT(const U8 te, const F32 t) +{ + if (te >= mNumTEs) + { + llwarns << "Setting nonexistent face" << llendl; + return 0; + } + + F32 s, ignore; + mTextureList[te].getOffset(&s, &ignore); + return mTextureList[te].setOffset(s,t); +} + + +//=============================================================== +S32 LLPrimitive::setTERotation(const U8 te, const F32 r) +{ + // if we're asking for a non-existent face, return null + if (te >= mNumTEs) + { + llwarns << "Setting nonexistent face" << llendl; + return 0; + } + + return mTextureList[te].setRotation(r); +} + + +//=============================================================== +S32 LLPrimitive::setTEBumpShinyFullbright(const U8 te, const U8 bump) +{ + // if we're asking for a non-existent face, return null + if (te >= mNumTEs) + { + llwarns << "setting non-existent te " << te << llendl + return 0; + } + + return mTextureList[te].setBumpShinyFullbright( bump ); +} + +S32 LLPrimitive::setTEMediaTexGen(const U8 te, const U8 media) +{ + // if we're asking for a non-existent face, return null + if (te >= mNumTEs) + { + llwarns << "setting non-existent te " << te << llendl + return 0; + } + + return mTextureList[te].setMediaTexGen( media ); +} + +S32 LLPrimitive::setTEBumpmap(const U8 te, const U8 bump) +{ + // if we're asking for a non-existent face, return null + if (te >= mNumTEs) + { + llwarns << "setting non-existent te " << te << llendl + return 0; + } + + return mTextureList[te].setBumpmap( bump ); +} + +S32 LLPrimitive::setTEBumpShiny(const U8 te, const U8 bump_shiny) +{ + // if we're asking for a non-existent face, return null + if (te >= mNumTEs) + { + llwarns << "setting non-existent te " << te << llendl + return 0; + } + + return mTextureList[te].setBumpShiny( bump_shiny ); +} + +S32 LLPrimitive::setTETexGen(const U8 te, const U8 texgen) +{ + // if we're asking for a non-existent face, return null + if (te >= mNumTEs) + { + llwarns << "setting non-existent te " << te << llendl + return 0; + } + + return mTextureList[te].setTexGen( texgen ); +} + +S32 LLPrimitive::setTEShiny(const U8 te, const U8 shiny) +{ + // if we're asking for a non-existent face, return null + if (te >= mNumTEs) + { + llwarns << "setting non-existent te " << te << llendl + return 0; + } + + return mTextureList[te].setShiny( shiny ); +} + +S32 LLPrimitive::setTEFullbright(const U8 te, const U8 fullbright) +{ + // if we're asking for a non-existent face, return null + if (te >= mNumTEs) + { + llwarns << "setting non-existent te " << te << llendl + return 0; + } + + return mTextureList[te].setFullbright( fullbright ); +} + +S32 LLPrimitive::setTEMediaFlags(const U8 te, const U8 media_flags) +{ + // if we're asking for a non-existent face, return null + if (te >= mNumTEs) + { + llwarns << "setting non-existent te " << te << llendl + return 0; + } + + return mTextureList[te].setMediaFlags( media_flags ); +} + + +LLPCode LLPrimitive::legacyToPCode(const U8 legacy) +{ + LLPCode pcode = 0; + + switch (legacy) + { + /* + case BOX: + pcode = LL_PCODE_CUBE; + break; + case CYLINDER: + pcode = LL_PCODE_CYLINDER; + break; + case CONE: + pcode = LL_PCODE_CONE; + break; + case HALF_CONE: + pcode = LL_PCODE_CONE_HEMI; + break; + case HALF_CYLINDER: + pcode = LL_PCODE_CYLINDER_HEMI; + break; + case HALF_SPHERE: + pcode = LL_PCODE_SPHERE_HEMI; + break; + case PRISM: + pcode = LL_PCODE_PRISM; + break; + case PYRAMID: + pcode = LL_PCODE_PYRAMID; + break; + case SPHERE: + pcode = LL_PCODE_SPHERE; + break; + case TETRAHEDRON: + pcode = LL_PCODE_TETRAHEDRON; + break; + case DEMON: + pcode = LL_PCODE_LEGACY_DEMON; + break; + case LSL_TEST: + pcode = LL_PCODE_LEGACY_LSL_TEST; + break; + case ORACLE: + pcode = LL_PCODE_LEGACY_ORACLE; + break; + case TEXTBUBBLE: + pcode = LL_PCODE_LEGACY_TEXT_BUBBLE; + break; + case ATOR: + pcode = LL_PCODE_LEGACY_ATOR; + break; + case BASIC_SHOT: + pcode = LL_PCODE_LEGACY_SHOT; + break; + case BIG_SHOT: + pcode = LL_PCODE_LEGACY_SHOT_BIG; + break; + case BIRD: + pcode = LL_PCODE_LEGACY_BIRD; + break; + case ROCK: + pcode = LL_PCODE_LEGACY_ROCK; + break; + case SMOKE: + pcode = LL_PCODE_LEGACY_SMOKE; + break; + case SPARK: + pcode = LL_PCODE_LEGACY_SPARK; + break; + */ + case PRIMITIVE_VOLUME: + pcode = LL_PCODE_VOLUME; + break; + case GRASS: + pcode = LL_PCODE_LEGACY_GRASS; + break; + case PART_SYS: + pcode = LL_PCODE_LEGACY_PART_SYS; + break; + case PLAYER: + pcode = LL_PCODE_LEGACY_AVATAR; + break; + case TREE: + pcode = LL_PCODE_LEGACY_TREE; + break; + case TREE_NEW: + pcode = LL_PCODE_TREE_NEW; + break; + default: + llwarns << "Unknown legacy code " << legacy << "!" << llendl; + } + + return pcode; +} + +U8 LLPrimitive::pCodeToLegacy(const LLPCode pcode) +{ + U8 legacy; + switch (pcode) + { +/* + case LL_PCODE_CUBE: + legacy = BOX; + break; + case LL_PCODE_CYLINDER: + legacy = CYLINDER; + break; + case LL_PCODE_CONE: + legacy = CONE; + break; + case LL_PCODE_CONE_HEMI: + legacy = HALF_CONE; + break; + case LL_PCODE_CYLINDER_HEMI: + legacy = HALF_CYLINDER; + break; + case LL_PCODE_SPHERE_HEMI: + legacy = HALF_SPHERE; + break; + case LL_PCODE_PRISM: + legacy = PRISM; + break; + case LL_PCODE_PYRAMID: + legacy = PYRAMID; + break; + case LL_PCODE_SPHERE: + legacy = SPHERE; + break; + case LL_PCODE_TETRAHEDRON: + legacy = TETRAHEDRON; + break; + case LL_PCODE_LEGACY_ATOR: + legacy = ATOR; + break; + case LL_PCODE_LEGACY_SHOT: + legacy = BASIC_SHOT; + break; + case LL_PCODE_LEGACY_SHOT_BIG: + legacy = BIG_SHOT; + break; + case LL_PCODE_LEGACY_BIRD: + legacy = BIRD; + break; + case LL_PCODE_LEGACY_DEMON: + legacy = DEMON; + break; + case LL_PCODE_LEGACY_LSL_TEST: + legacy = LSL_TEST; + break; + case LL_PCODE_LEGACY_ORACLE: + legacy = ORACLE; + break; + case LL_PCODE_LEGACY_ROCK: + legacy = ROCK; + break; + case LL_PCODE_LEGACY_TEXT_BUBBLE: + legacy = TEXTBUBBLE; + break; + case LL_PCODE_LEGACY_SMOKE: + legacy = SMOKE; + break; + case LL_PCODE_LEGACY_SPARK: + legacy = SPARK; + break; +*/ + case LL_PCODE_VOLUME: + legacy = PRIMITIVE_VOLUME; + break; + case LL_PCODE_LEGACY_GRASS: + legacy = GRASS; + break; + case LL_PCODE_LEGACY_PART_SYS: + legacy = PART_SYS; + break; + case LL_PCODE_LEGACY_AVATAR: + legacy = PLAYER; + break; + case LL_PCODE_LEGACY_TREE: + legacy = TREE; + break; + case LL_PCODE_TREE_NEW: + legacy = TREE_NEW; + break; + default: + llwarns << "Unknown pcode " << (S32)pcode << ":" << pcode << "!" << llendl; + return 0; + } + return legacy; +} + + +// static +// Don't crash or llerrs here! This function is used for debug strings. +const char * LLPrimitive::pCodeToString(const LLPCode pcode) +{ + static char pcode_string[255]; + + U8 base_code = pcode & LL_PCODE_BASE_MASK; + pcode_string[0] = 0; + if (!pcode) + { + sprintf(pcode_string, "null"); + } + else if ((base_code) == LL_PCODE_LEGACY) + { + // It's a legacy object + switch (pcode) + { + case LL_PCODE_LEGACY_GRASS: + sprintf(pcode_string, "grass"); + break; + case LL_PCODE_LEGACY_PART_SYS: + sprintf(pcode_string, "particle system"); + break; + case LL_PCODE_LEGACY_AVATAR: + sprintf(pcode_string, "avatar"); + break; + case LL_PCODE_LEGACY_TEXT_BUBBLE: + sprintf(pcode_string, "text bubble"); + break; + case LL_PCODE_LEGACY_TREE: + sprintf(pcode_string, "tree"); + break; + case LL_PCODE_TREE_NEW: + sprintf(pcode_string, "tree_new"); + break; + default: + sprintf(pcode_string, "unknown legacy pcode %i",(U32)pcode); + } + } + else + { + char shape[32]; + char mask[32]; + if (base_code == LL_PCODE_CUBE) + { + sprintf(shape, "cube"); + } + else if (base_code == LL_PCODE_CYLINDER) + { + sprintf(shape, "cylinder"); + } + else if (base_code == LL_PCODE_CONE) + { + sprintf(shape, "cone"); + } + else if (base_code == LL_PCODE_PRISM) + { + sprintf(shape, "prism"); + } + else if (base_code == LL_PCODE_PYRAMID) + { + sprintf(shape, "pyramid"); + } + else if (base_code == LL_PCODE_SPHERE) + { + sprintf(shape, "sphere"); + } + else if (base_code == LL_PCODE_TETRAHEDRON) + { + sprintf(shape, "tetrahedron"); + } + else if (base_code == LL_PCODE_VOLUME) + { + sprintf(shape, "volume"); + } + else if (base_code == LL_PCODE_APP) + { + sprintf(shape, "app"); + } + else + { + llwarns << "Unknown base mask for pcode: " << base_code << llendl; + } + + U8 mask_code = pcode & (~LL_PCODE_BASE_MASK); + if (base_code == LL_PCODE_APP) + { + sprintf(mask, "%x", mask_code); + } + else if (mask_code & LL_PCODE_HEMI_MASK) + { + sprintf(mask, "hemi"); + } + else if (mask != 0) + { + sprintf(mask, "%x", mask_code); + } + else + { + mask[0] = 0; + } + + if (mask[0]) + { + sprintf(pcode_string, "%s-%s", shape, mask); + } + else + { + sprintf(pcode_string, "%s", shape); + } + } + return pcode_string; +} + + +void LLPrimitive::copyTEs(const LLPrimitive *primitivep) +{ + U32 i; + if (primitivep->getNumTEs() != getNumTEs()) + { + llwarns << "Primitives don't have same number of TE's" << llendl; + } + U32 num_tes = llmin(primitivep->getNumTEs(), getNumTEs()); + for (i = 0; i < num_tes; i++) + { + const LLTextureEntry *tep = primitivep->getTE(i); + F32 s, t; + setTETexture(i, tep->getID()); + setTEColor(i, tep->getColor()); + tep->getScale(&s, &t); + setTEScale(i, s, t); + tep->getOffset(&s, &t); + setTEOffset(i, s, t); + setTERotation(i, tep->getRotation()); + setTEBumpShinyFullbright(i, tep->getBumpShinyFullbright()); + setTEMediaTexGen(i, tep->getMediaTexGen()); + } +} + +S32 face_index_from_id(LLFaceID face_ID, const std::vector<LLProfile::Face>& faceArray) +{ + S32 i; + for (i = 0; i < (S32)faceArray.size(); i++) + { + if (faceArray[i].mFaceID == face_ID) + { + return i; + } + } + return -1; +} + +BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume) +{ + LLVolume *volumep; + if (unique_volume) + { + F32 volume_detail = LLVolumeLODGroup::getVolumeScaleFromDetail(detail); + if (mVolumep.notNull() && volume_params == mVolumep->getParams() && (volume_detail == mVolumep->getDetail())) + { + return FALSE; + } + volumep = new LLVolume(volume_params, volume_detail, FALSE, TRUE); + } + else + { + if (mVolumep.notNull()) + { + F32 volume_detail = LLVolumeLODGroup::getVolumeScaleFromDetail(detail); + if (volume_params == mVolumep->getParams() && (volume_detail == mVolumep->getDetail())) + { + return FALSE; + } + } + + volumep = gVolumeMgr->getVolume(volume_params, detail); + if (volumep == mVolumep) + { + gVolumeMgr->cleanupVolume( volumep ); // gVolumeMgr->getVolume() creates a reference, but we don't need a second one. + return TRUE; + } + } + + setChanged(GEOMETRY); + + + if (!mVolumep) + { + mVolumep = volumep; + //mFaceMask = mVolumep->generateFaceMask(); + setNumTEs(mVolumep->getNumFaces()); + return TRUE; + } + + U32 old_face_mask = mVolumep->mFaceMask; + + S32 face_bit = 0; + S32 cur_mask = 0; + + // grab copies of the old faces so we can determine the TE mappings... + std::vector<LLProfile::Face> old_faces; // list of old faces for remapping texture entries + LLTextureEntry old_tes[9]; + + for (S32 face = 0; face < mVolumep->getNumFaces(); face++) + { + old_faces.push_back(mVolumep->getProfile().mFaces[face]); + } + + for (face_bit = 0; face_bit < 9; face_bit++) + { + cur_mask = 0x1 << face_bit; + if (old_face_mask & cur_mask) + { + S32 te_index = face_index_from_id(cur_mask, old_faces); + old_tes[face_bit] = *getTE(te_index); + //llinfos << face_bit << ":" << te_index << ":" << old_tes[face_bit].getID() << llendl; + } + } + + + // build the new object + gVolumeMgr->cleanupVolume(mVolumep); + mVolumep = volumep; + + U32 new_face_mask = mVolumep->mFaceMask; + S32 i; + + /* + LLString old_mask_string; + for (i = 0; i < 9; i++) + { + if (old_face_mask & (1 << i)) + { + old_mask_string.append("1"); + } + else + { + old_mask_string.append("0"); + } + } + LLString new_mask_string; + for (i = 0; i < 9; i++) + { + if (new_face_mask & (1 << i)) + { + new_mask_string.append("1"); + } + else + { + new_mask_string.append("0"); + } + } + + llinfos << "old mask: " << old_mask_string << llendl; + llinfos << "new mask: " << new_mask_string << llendl; + */ + + + if (old_face_mask == new_face_mask) + { + // nothing to do + return TRUE; + } + + if (mVolumep->getNumFaces() == 0 && new_face_mask != 0) + { + llwarns << "Object with 0 faces found...INCORRECT!" << llendl; + setNumTEs(mVolumep->getNumFaces()); + return TRUE; + } + + + S32 face_mapping[9]; + for (face_bit = 0; face_bit < 9; face_bit++) + { + face_mapping[face_bit] = face_bit; + } + + // Generate the face-type mappings + for (face_bit = 0; face_bit < 9; face_bit++) + { + cur_mask = 0x1 << face_bit; + if (!(new_face_mask & cur_mask)) + { + // Face doesn't exist in new map. + face_mapping[face_bit] = -1; + continue; + } + else if (old_face_mask & cur_mask) + { + // Face exists in new and old map. + face_mapping[face_bit] = face_bit; + continue; + } + + // OK, how we've got a mismatch, where we have to fill a new face with one from + // the old face. + if (cur_mask & (LL_FACE_PATH_BEGIN | LL_FACE_PATH_END | LL_FACE_INNER_SIDE)) + { + // It's a top/bottom/hollow interior face. + if (old_face_mask & LL_FACE_PATH_END) + { + face_mapping[face_bit] = 1; + continue; + } + else + { + S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0; + for (i = 0; i < 4; i++) + { + if (old_face_mask & cur_outer_mask) + { + face_mapping[face_bit] = 5 + i; + break; + } + cur_outer_mask <<= 1; + } + if (i == 4) + { + llwarns << "No path end or outer face in volume!" << llendl; + } + continue; + } + } + + if (cur_mask & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END)) + { + // A cut slice. Use the hollow interior if we have it. + if (old_face_mask & LL_FACE_INNER_SIDE) + { + face_mapping[face_bit] = 2; + continue; + } + + // No interior, use the bottom face. + // Could figure out which of the outer faces was nearest, but that would be harder. + if (old_face_mask & LL_FACE_PATH_END) + { + face_mapping[face_bit] = 1; + continue; + } + else + { + S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0; + for (i = 0; i < 4; i++) + { + if (old_face_mask & cur_outer_mask) + { + face_mapping[face_bit] = 5 + i; + break; + } + cur_outer_mask <<= 1; + } + if (i == 4) + { + llwarns << "No path end or outer face in volume!" << llendl; + } + continue; + } + } + + // OK, the face that's missing is an outer face... + // Pull from the nearest adjacent outer face (there's always guaranteed to be one... + S32 cur_outer = face_bit - 5; + S32 min_dist = 5; + S32 min_outer_bit = -1; + S32 i; + for (i = 0; i < 4; i++) + { + if (old_face_mask & (LL_FACE_OUTER_SIDE_0 << i)) + { + S32 dist = abs(i - cur_outer); + if (dist < min_dist) + { + min_dist = dist; + min_outer_bit = i + 5; + } + } + } + if (-1 == min_outer_bit) + { + llinfos << (LLVolume *)mVolumep << llendl; + llwarns << "Bad! No outer faces, impossible!" << llendl; + } + face_mapping[face_bit] = min_outer_bit; + } + + + setNumTEs(mVolumep->getNumFaces()); + for (face_bit = 0; face_bit < 9; face_bit++) + { + cur_mask = 0x1 << face_bit; + if (new_face_mask & cur_mask) + { + if (-1 == face_mapping[face_bit]) + { + llwarns << "No mapping from old face to new face!" << llendl; + } + + S32 te_num = face_index_from_id(cur_mask, mVolumep->getProfile().mFaces); + setTE(te_num, old_tes[face_mapping[face_bit]]); + } + } + return TRUE; +} + +BOOL LLPrimitive::setMaterial(U8 material) +{ + if (material != mMaterial) + { + mMaterial = material; + return TRUE; + } + else + { + return FALSE; + } +} + +void LLPrimitive::setTEArrays(const U8 size, + const LLUUID* image_ids, + const F32* scale_s, + const F32* scale_t) +{ + S32 cur_size = size; + if (cur_size > getNumTEs()) + { + llwarns << "Trying to set more TEs than exist!" << llendl; + cur_size = getNumTEs(); + } + + S32 i; + // Copy over image information + for (i = 0; i < cur_size; i++) + { + // This is very BAD!!!!!! + if (image_ids != NULL) + { + setTETexture(i,image_ids[i]); + } + if (scale_s && scale_t) + { + setTEScale(i, scale_s[i], scale_t[i]); + } + } + + if (i < getNumTEs()) + { + cur_size--; + for (i=i; i < getNumTEs(); i++) // the i=i removes a gcc warning + { + if (image_ids != NULL) + { + setTETexture(i, image_ids[cur_size]); + } + if (scale_s && scale_t) + { + setTEScale(i, scale_s[cur_size], scale_t[cur_size]); + } + } + } +} + +const F32 LL_MAX_SCALE_S = 100.0f; +const F32 LL_MAX_SCALE_T = 100.0f; +S32 LLPrimitive::packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const +{ + S32 face_index; + S32 i; + U64 exception_faces; + U8 *start_loc = cur_ptr; + + htonmemcpy(cur_ptr,data_ptr + (last_face_index * data_size), type, data_size); + cur_ptr += data_size; + + for (face_index = last_face_index-1; face_index >= 0; face_index--) + { + BOOL already_sent = FALSE; + for (i = face_index+1; i <= last_face_index; i++) + { + if (!memcmp(data_ptr+(data_size *face_index), data_ptr+(data_size *i), data_size)) + { + already_sent = TRUE; + break; + } + } + + if (!already_sent) + { + exception_faces = 0; + for (i = face_index; i >= 0; i--) + { + if (!memcmp(data_ptr+(data_size *face_index), data_ptr+(data_size *i), data_size)) + { + exception_faces |= (1 << i); + } + } + + //assign exception faces to cur_ptr + if (exception_faces >= (0x1 << 7)) + { + if (exception_faces >= (0x1 << 14)) + { + if (exception_faces >= (0x1 << 21)) + { + if (exception_faces >= (0x1 << 28)) + { + *cur_ptr++ = (U8)(((exception_faces >> 28) & 0x7F) | 0x80); + } + *cur_ptr++ = (U8)(((exception_faces >> 21) & 0x7F) | 0x80); + } + *cur_ptr++ = (U8)(((exception_faces >> 14) & 0x7F) | 0x80); + } + *cur_ptr++ = (U8)(((exception_faces >> 7) & 0x7F) | 0x80); + } + + *cur_ptr++ = (U8)(exception_faces & 0x7F); + + htonmemcpy(cur_ptr,data_ptr + (face_index * data_size), type, data_size); + cur_ptr += data_size; + } + } + return (S32)(cur_ptr - start_loc); +} + +S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type) +{ + U8 *start_loc = cur_ptr; + U64 i; + htonmemcpy(data_ptr,cur_ptr, type,data_size); + cur_ptr += data_size; + + for (i = 1; i < face_count; i++) + { + // Already unswizzled, don't need to unswizzle it again! + memcpy(data_ptr+(i*data_size),data_ptr,data_size); + } + + while ((cur_ptr < buffer_end) && (*cur_ptr != 0)) + { +// llinfos << "TE exception" << llendl; + i = 0; + while (*cur_ptr & 0x80) + { + i |= ((*cur_ptr++) & 0x7F); + i = i << 7; + } + + i |= *cur_ptr++; + + for (S32 j = 0; j < face_count; j++) + { + if (i & 0x01) + { + htonmemcpy(data_ptr+(j*data_size),cur_ptr,type,data_size); +// char foo[64]; +// sprintf(foo,"%x %x",*(data_ptr+(j*data_size)), *(data_ptr+(j*data_size)+1)); +// llinfos << "Assigning " << foo << " to face " << j << llendl; + } + i = i >> 1; + } + cur_ptr += data_size; + } + return (S32)(cur_ptr - start_loc); +} + + +// Pack information about all texture entries into container: +// { TextureEntry Variable 2 } +// Includes information about image ID, color, scale S,T, offset S,T and rotation +BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const +{ + const U32 MAX_TES = 32; + + U8 image_ids[MAX_TES*16]; + U8 colors[MAX_TES*4]; + S16 scale_s[MAX_TES]; + S16 scale_t[MAX_TES]; + S16 offset_s[MAX_TES]; + S16 offset_t[MAX_TES]; + S16 image_rot[MAX_TES]; + U8 bump[MAX_TES]; + U8 media_flags[MAX_TES]; + + const U32 MAX_TE_BUFFER = 4096; + U8 packed_buffer[MAX_TE_BUFFER]; + U8 *cur_ptr = packed_buffer; + + S32 last_face_index = getNumTEs() - 1; + + if (last_face_index > -1) + { + // ...if we hit the front, send one image id + S8 face_index; + LLColor4U coloru; + for (face_index = 0; face_index <= last_face_index; face_index++) + { + // Directly sending image_ids is not safe! + memcpy(&image_ids[face_index*16],getTE(face_index)->getID().mData,16); + + // Cast LLColor4 to LLColor4U + coloru.setVec( getTE(face_index)->getColor() ); + + // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) + // as all zeros. However, the subtraction and addition must be done in unsigned + // byte space, not in float space, otherwise off-by-one errors occur. JC + colors[4*face_index] = 255 - coloru.mV[0]; + colors[4*face_index + 1] = 255 - coloru.mV[1]; + colors[4*face_index + 2] = 255 - coloru.mV[2]; + colors[4*face_index + 3] = 255 - coloru.mV[3]; + + const LLTextureEntry* te = getTE(face_index); + scale_s[face_index] = (S16) llround(((llclamp(te->mScaleS,-LL_MAX_SCALE_S, LL_MAX_SCALE_S)-1.0f)/(LL_MAX_SCALE_S+1.f) * (F32)0x7FFF)); + scale_t[face_index] = (S16) llround(((llclamp(te->mScaleT,-LL_MAX_SCALE_T, LL_MAX_SCALE_T)-1.0f)/(LL_MAX_SCALE_T+1.f) * (F32)0x7FFF)); + offset_s[face_index] = (S16) llround((llclamp(te->mOffsetS,-1.0f,1.0f) * (F32)0x7FFF)) ; + offset_t[face_index] = (S16) llround((llclamp(te->mOffsetT,-1.0f,1.0f) * (F32)0x7FFF)) ; + image_rot[face_index] = (S16) llround(((fmod(te->mRotation, F_TWO_PI)/F_TWO_PI) * (F32)0x7FFF)); + bump[face_index] = te->getBumpShinyFullbright(); + media_flags[face_index] = te->getMediaTexGen(); +// llinfos << "BUMP pack [" << (S32)face_index << "]=" << (S32) bump[face_index] << llendl; + } + + cur_ptr += packTEField(cur_ptr, (U8 *)image_ids, sizeof(LLUUID),last_face_index, MVT_LLUUID); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)colors, 4 ,last_face_index, MVT_U8); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)scale_s, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)scale_t, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)offset_s, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)offset_t, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)image_rot, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)bump, 1 ,last_face_index, MVT_U8); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)media_flags, 1 ,last_face_index, MVT_U8); + } + mesgsys->addBinaryDataFast(_PREHASH_TextureEntry, packed_buffer, (S32)(cur_ptr - packed_buffer)); + + return FALSE; +} + + +BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const +{ + const U32 MAX_TES = 32; + + U8 image_ids[MAX_TES*16]; + U8 colors[MAX_TES*4]; + S16 scale_s[MAX_TES]; + S16 scale_t[MAX_TES]; + S16 offset_s[MAX_TES]; + S16 offset_t[MAX_TES]; + S16 image_rot[MAX_TES]; + U8 bump[MAX_TES]; + U8 media_flags[MAX_TES]; + + const U32 MAX_TE_BUFFER = 4096; + U8 packed_buffer[MAX_TE_BUFFER]; + U8 *cur_ptr = packed_buffer; + + S32 last_face_index = getNumTEs() - 1; + + if (last_face_index > -1) + { + // ...if we hit the front, send one image id + S8 face_index; + LLColor4U coloru; + for (face_index = 0; face_index <= last_face_index; face_index++) + { + // Directly sending image_ids is not safe! + memcpy(&image_ids[face_index*16],getTE(face_index)->getID().mData,16); + + // Cast LLColor4 to LLColor4U + coloru.setVec( getTE(face_index)->getColor() ); + + // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) + // as all zeros. However, the subtraction and addition must be done in unsigned + // byte space, not in float space, otherwise off-by-one errors occur. JC + colors[4*face_index] = 255 - coloru.mV[0]; + colors[4*face_index + 1] = 255 - coloru.mV[1]; + colors[4*face_index + 2] = 255 - coloru.mV[2]; + colors[4*face_index + 3] = 255 - coloru.mV[3]; + + const LLTextureEntry* te = getTE(face_index); + scale_s[face_index] = (S16) llround(((llclamp(te->mScaleS,-LL_MAX_SCALE_S, LL_MAX_SCALE_S)-1.0f)/(LL_MAX_SCALE_S+1.f) * (F32)0x7FFF)); + scale_t[face_index] = (S16) llround(((llclamp(te->mScaleT,-LL_MAX_SCALE_T, LL_MAX_SCALE_T)-1.0f)/(LL_MAX_SCALE_T+1.f) * (F32)0x7FFF)); + offset_s[face_index] = (S16) llround((llclamp(te->mOffsetS,-1.0f,1.0f) * (F32)0x7FFF)) ; + offset_t[face_index] = (S16) llround((llclamp(te->mOffsetT,-1.0f,1.0f) * (F32)0x7FFF)) ; + image_rot[face_index] = (S16) llround(((fmod(te->mRotation, F_TWO_PI)/F_TWO_PI) * (F32)0x7FFF)); + bump[face_index] = te->getBumpShinyFullbright(); + media_flags[face_index] = te->getMediaTexGen(); + +// llinfos << "BUMP pack (Datapacker) [" << (S32)face_index << "]=" << (S32) bump[face_index] << llendl; + } + + cur_ptr += packTEField(cur_ptr, (U8 *)image_ids, sizeof(LLUUID),last_face_index, MVT_LLUUID); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)colors, 4 ,last_face_index, MVT_U8); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)scale_s, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)scale_t, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)offset_s, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)offset_t, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)image_rot, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)bump, 1 ,last_face_index, MVT_U8); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)media_flags, 1 ,last_face_index, MVT_U8); + } + + dp.packBinaryData(packed_buffer, (S32)(cur_ptr - packed_buffer), "TextureEntry"); + return FALSE; +} + +S32 LLPrimitive::unpackTEMessage(LLMessageSystem *mesgsys, char *block_name) +{ + return(unpackTEMessage(mesgsys,block_name,-1)); +} + +S32 LLPrimitive::unpackTEMessage(LLMessageSystem *mesgsys, char *block_name, const S32 block_num) +{ + // use a negative block_num to indicate a single-block read (a non-variable block) + S32 retval = 0; + const U32 MAX_TES = 32; + + // Avoid construction of 32 UUIDs per call. JC + + U8 image_data[MAX_TES*16]; + U8 colors[MAX_TES*4]; + S16 scale_s[MAX_TES]; + S16 scale_t[MAX_TES]; + S16 offset_s[MAX_TES]; + S16 offset_t[MAX_TES]; + S16 image_rot[MAX_TES]; + U8 bump[MAX_TES]; + U8 media_flags[MAX_TES]; + + const U32 MAX_TE_BUFFER = 4096; + U8 packed_buffer[MAX_TE_BUFFER]; + U8 *cur_ptr = packed_buffer; + + U32 size; + U32 face_count = 0; + + if (block_num < 0) + { + size = mesgsys->getSizeFast(block_name, _PREHASH_TextureEntry); + } + else + { + size = mesgsys->getSizeFast(block_name, block_num, _PREHASH_TextureEntry); + } + + if (size == 0) + { + return retval; + } + + if (block_num < 0) + { + mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, packed_buffer, 0, 0, MAX_TE_BUFFER); + } + else + { + mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, packed_buffer, 0, block_num, MAX_TE_BUFFER); + } + + face_count = getNumTEs(); + + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_data, 16, face_count, MVT_LLUUID); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)colors, 4, face_count, MVT_U8); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_s, 2, face_count, MVT_S16Array); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_t, 2, face_count, MVT_S16Array); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_s, 2, face_count, MVT_S16Array); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_t, 2, face_count, MVT_S16Array); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_rot, 2, face_count, MVT_S16Array); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)bump, 1, face_count, MVT_U8); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)media_flags, 1, face_count, MVT_U8); + + LLColor4 color; + LLColor4U coloru; + for (U32 i = 0; i < face_count; i++) + { + retval |= setTETexture(i, ((LLUUID*)image_data)[i]); + retval |= setTEScale(i, + floor((1.0f + ((((F32)scale_s[i] / (F32)0x7FFF)) * (LL_MAX_SCALE_S+1.f))) * 100.f + 0.5f) / 100.f, + floor((1.0f + ((((F32)scale_t[i] / (F32)0x7FFF)) * (LL_MAX_SCALE_T+1.f))) * 100.f + 0.5f) / 100.f); + retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF); + retval |= setTERotation(i, ((F32)image_rot[i]/ (F32)0x7FFF) * F_TWO_PI); + retval |= setTEBumpShinyFullbright(i, bump[i]); + retval |= setTEMediaTexGen(i, media_flags[i]); + coloru = LLColor4U(colors + 4*i); + + // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) + // as all zeros. However, the subtraction and addition must be done in unsigned + // byte space, not in float space, otherwise off-by-one errors occur. JC + color.mV[VRED] = F32(255 - coloru.mV[VRED]) / 255.f; + color.mV[VGREEN] = F32(255 - coloru.mV[VGREEN]) / 255.f; + color.mV[VBLUE] = F32(255 - coloru.mV[VBLUE]) / 255.f; + color.mV[VALPHA] = F32(255 - coloru.mV[VALPHA]) / 255.f; + + retval |= setTEColor(i, color); + } + + return retval; +} + +S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) +{ + // use a negative block_num to indicate a single-block read (a non-variable block) + S32 retval = 0; + const U32 MAX_TES = 32; + + // Avoid construction of 32 UUIDs per call + static LLUUID image_ids[MAX_TES]; + + U8 image_data[MAX_TES*16]; + U8 colors[MAX_TES*4]; + S16 scale_s[MAX_TES]; + S16 scale_t[MAX_TES]; + S16 offset_s[MAX_TES]; + S16 offset_t[MAX_TES]; + S16 image_rot[MAX_TES]; + U8 bump[MAX_TES]; + U8 media_flags[MAX_TES]; + + const U32 MAX_TE_BUFFER = 4096; + U8 packed_buffer[MAX_TE_BUFFER]; + U8 *cur_ptr = packed_buffer; + + S32 size; + U32 face_count = 0; + + if (!dp.unpackBinaryData(packed_buffer, size, "TextureEntry")) + { + retval = TEM_INVALID; + llwarns << "Bad texture entry block! Abort!" << llendl; + return retval; + } + + if (size == 0) + { + return retval; + } + + face_count = getNumTEs(); + U32 i; + + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_data, 16, face_count, MVT_LLUUID); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)colors, 4, face_count, MVT_U8); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_s, 2, face_count, MVT_S16Array); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_t, 2, face_count, MVT_S16Array); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_s, 2, face_count, MVT_S16Array); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_t, 2, face_count, MVT_S16Array); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_rot, 2, face_count, MVT_S16Array); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)bump, 1, face_count, MVT_U8); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)media_flags, 1, face_count, MVT_U8); + + for (i = 0; i < face_count; i++) + { +// llinfos << "BUMP unpack (Datapacker) [" << i << "]=" << S32(bump[i]) <<llendl; + memcpy(image_ids[i].mData,&image_data[i*16],16); + } + + LLColor4 color; + LLColor4U coloru; + for (i = 0; i < face_count; i++) + { + retval |= setTETexture(i, image_ids[i]); + retval |= setTEScale(i, + floor((1.0f + ((((F32)scale_s[i] / (F32)0x7FFF)) * (LL_MAX_SCALE_S+1.f))) * 100.f + 0.5f) / 100.f, + floor((1.0f + ((((F32)scale_t[i] / (F32)0x7FFF)) * (LL_MAX_SCALE_T+1.f))) * 100.f + 0.5f) / 100.f); + retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF); + retval |= setTERotation(i, ((F32)image_rot[i]/ (F32)0x7FFF) * F_TWO_PI); + retval |= setTEBumpShinyFullbright(i, bump[i]); + retval |= setTEMediaTexGen(i, media_flags[i]); + coloru = LLColor4U(colors + 4*i); + + // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) + // as all zeros. However, the subtraction and addition must be done in unsigned + // byte space, not in float space, otherwise off-by-one errors occur. JC + color.mV[VRED] = F32(255 - coloru.mV[VRED]) / 255.f; + color.mV[VGREEN] = F32(255 - coloru.mV[VGREEN]) / 255.f; + color.mV[VBLUE] = F32(255 - coloru.mV[VBLUE]) / 255.f; + color.mV[VALPHA] = F32(255 - coloru.mV[VALPHA]) / 255.f; + + retval |= setTEColor(i, color); + } + + return retval; +} + +void LLPrimitive::setTextureList(LLTextureEntry *listp) +{ + LLTextureEntry* old_texture_list = mTextureList; + mTextureList = listp; + delete[] old_texture_list; +} + +//============================================================================ + +LLLightParams::LLLightParams() +{ + mColor.setToWhite(); + mRadius = 10.f; + mCutoff = 0.0f; + mFalloff = 0.75f; + + mType = PARAMS_LIGHT; +} + +BOOL LLLightParams::pack(LLDataPacker &dp) const +{ + LLColor4U color4u(mColor); + dp.packColor4U(color4u, "color"); + dp.packF32(mRadius, "radius"); + dp.packF32(mCutoff, "cutoff"); + dp.packF32(mFalloff, "falloff"); + return TRUE; +} + +BOOL LLLightParams::unpack(LLDataPacker &dp) +{ + LLColor4U color4u; + dp.unpackColor4U(color4u, "color"); + mColor = LLColor4(color4u); + dp.unpackF32(mRadius, "radius"); + dp.unpackF32(mCutoff, "cutoff"); + dp.unpackF32(mFalloff, "falloff"); + return TRUE; +} + +bool LLLightParams::operator==(const LLNetworkData& data) const +{ + if (data.mType != PARAMS_LIGHT) + { + return false; + } + const LLLightParams *param = (const LLLightParams*)&data; + if (param->mColor != mColor || + param->mRadius != mRadius || + param->mCutoff != mCutoff || + param->mFalloff != mFalloff) + { + return false; + } + return true; +} + +void LLLightParams::copy(const LLNetworkData& data) +{ + const LLLightParams *param = (LLLightParams*)&data; + mType = param->mType; + mColor = param->mColor; + mRadius = param->mRadius; + mCutoff = param->mCutoff; + mFalloff = param->mFalloff; +} + +//============================================================================ + +LLFlexibleObjectData::LLFlexibleObjectData() +{ + mSimulateLOD = FLEXIBLE_OBJECT_DEFAULT_NUM_SECTIONS; + mGravity = FLEXIBLE_OBJECT_DEFAULT_GRAVITY; + mAirFriction = FLEXIBLE_OBJECT_DEFAULT_AIR_FRICTION; + mWindSensitivity = FLEXIBLE_OBJECT_DEFAULT_WIND_SENSITIVITY; + mTension = FLEXIBLE_OBJECT_DEFAULT_TENSION; + //mUsingCollisionSphere = FLEXIBLE_OBJECT_DEFAULT_USING_COLLISION_SPHERE; + //mRenderingCollisionSphere = FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE; + mUserForce = LLVector3(0.f, 0.f, 0.f); + + mType = PARAMS_FLEXIBLE; +} + +BOOL LLFlexibleObjectData::pack(LLDataPacker &dp) const +{ + // Custom, uber-svelte pack "softness" in upper bits of tension & drag + U8 bit1 = (mSimulateLOD & 2) << 6; + U8 bit2 = (mSimulateLOD & 1) << 7; + dp.packU8((U8)(mTension*10.01f) + bit1, "tension"); + dp.packU8((U8)(mAirFriction*10.01f) + bit2, "drag"); + dp.packU8((U8)((mGravity+10.f)*10.01f), "gravity"); + dp.packU8((U8)(mWindSensitivity*10.01f), "wind"); + dp.packVector3(mUserForce, "userforce"); + return TRUE; +} + +BOOL LLFlexibleObjectData::unpack(LLDataPacker &dp) +{ + U8 tension, friction, gravity, wind; + U8 bit1, bit2; + dp.unpackU8(tension, "tension"); bit1 = (tension >> 6) & 2; + mTension = ((F32)(tension&0x7f))/10.f; + dp.unpackU8(friction, "drag"); bit2 = (friction >> 7) & 1; + mAirFriction = ((F32)(friction&0x7f))/10.f; + mSimulateLOD = bit1 | bit2; + dp.unpackU8(gravity, "gravity"); mGravity = ((F32)gravity)/10.f - 10.f; + dp.unpackU8(wind, "wind"); mWindSensitivity = ((F32)wind)/10.f; + if (dp.hasNext()) + { + dp.unpackVector3(mUserForce, "userforce"); + } + else + { + mUserForce.setVec(0.f, 0.f, 0.f); + } + return TRUE; +} + +bool LLFlexibleObjectData::operator==(const LLNetworkData& data) const +{ + if (data.mType != PARAMS_FLEXIBLE) + { + return false; + } + LLFlexibleObjectData *flex_data = (LLFlexibleObjectData*)&data; + return (mSimulateLOD == flex_data->mSimulateLOD && + mGravity == flex_data->mGravity && + mAirFriction == flex_data->mAirFriction && + mWindSensitivity == flex_data->mWindSensitivity && + mTension == flex_data->mTension && + mUserForce == flex_data->mUserForce); + //mUsingCollisionSphere == flex_data->mUsingCollisionSphere && + //mRenderingCollisionSphere == flex_data->mRenderingCollisionSphere +} + +void LLFlexibleObjectData::copy(const LLNetworkData& data) +{ + const LLFlexibleObjectData *flex_data = (LLFlexibleObjectData*)&data; + mSimulateLOD = flex_data->mSimulateLOD; + mGravity = flex_data->mGravity; + mAirFriction = flex_data->mAirFriction; + mWindSensitivity = flex_data->mWindSensitivity; + mTension = flex_data->mTension; + mUserForce = flex_data->mUserForce; + //mUsingCollisionSphere = flex_data->mUsingCollisionSphere; + //mRenderingCollisionSphere = flex_data->mRenderingCollisionSphere; +} diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h new file mode 100644 index 0000000000..3ad96bf6e1 --- /dev/null +++ b/indra/llprimitive/llprimitive.h @@ -0,0 +1,510 @@ +/** + * @file llprimitive.h + * @brief LLPrimitive base class + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_LLPRIMITIVE_H +#define LL_LLPRIMITIVE_H + +#include "lluuid.h" +#include "v3math.h" +#include "xform.h" +#include "message.h" +#include "llmemory.h" +#include "llvolume.h" +#include "lltextureentry.h" + +// Moved to stdtypes.h --JC +// typedef U8 LLPCode; +class LLMessageSystem; +class LLVolumeParams; +class LLColor4; +class LLColor3; +class LLTextureEntry; +class LLDataPacker; + +enum LLGeomType // NOTE: same vals as GL Ids +{ + LLInvalid = 0, + LLLineLoop = 2, + LLLineStrip = 3, + LLTriangles = 4, + LLTriStrip = 5, + LLTriFan = 6, + LLQuads = 7, + LLQuadStrip = 8 +}; + +class LLVolume; + +/** + * exported constants + */ +extern const F32 OBJECT_CUT_MIN; +extern const F32 OBJECT_CUT_MAX; +extern const F32 OBJECT_CUT_INC; +extern const F32 OBJECT_MIN_CUT_INC; +extern const F32 OBJECT_ROTATION_PRECISION; + +extern const F32 OBJECT_TWIST_MIN; +extern const F32 OBJECT_TWIST_MAX; +extern const F32 OBJECT_TWIST_INC; + +// This is used for linear paths, +// since twist is used in a slightly different manner. +extern const F32 OBJECT_TWIST_LINEAR_MIN; +extern const F32 OBJECT_TWIST_LINEAR_MAX; +extern const F32 OBJECT_TWIST_LINEAR_INC; + +extern const F32 OBJECT_MIN_HOLE_SIZE; +extern const F32 OBJECT_MAX_HOLE_SIZE_X; +extern const F32 OBJECT_MAX_HOLE_SIZE_Y; + +// Revolutions parameters. +extern const F32 OBJECT_REV_MIN; +extern const F32 OBJECT_REV_MAX; +extern const F32 OBJECT_REV_INC; + + +//============================================================================ + +// TomY: Base class for things that pack & unpack themselves +class LLNetworkData +{ +public: + // Extra parameter IDs + enum + { + PARAMS_FLEXIBLE = 0x10, + PARAMS_LIGHT = 0x20 + }; + +public: + U16 mType; + virtual ~LLNetworkData() {}; + virtual BOOL pack(LLDataPacker &dp) const = 0; + virtual BOOL unpack(LLDataPacker &dp) = 0; + virtual bool operator==(const LLNetworkData& data) const = 0; + virtual void copy(const LLNetworkData& data) = 0; +}; + +extern const F32 LIGHT_MIN_RADIUS; +extern const F32 LIGHT_DEFAULT_RADIUS; +extern const F32 LIGHT_MAX_RADIUS; +extern const F32 LIGHT_MIN_FALLOFF; +extern const F32 LIGHT_DEFAULT_FALLOFF; +extern const F32 LIGHT_MAX_FALLOFF; +extern const F32 LIGHT_MIN_CUTOFF; +extern const F32 LIGHT_DEFAULT_CUTOFF; +extern const F32 LIGHT_MAX_CUTOFF; + +class LLLightParams : public LLNetworkData +{ +protected: + LLColor4 mColor; // alpha = intensity + F32 mRadius; + F32 mFalloff; + F32 mCutoff; + +public: + LLLightParams(); + /*virtual*/ BOOL pack(LLDataPacker &dp) const; + /*virtual*/ BOOL unpack(LLDataPacker &dp); + /*virtual*/ bool operator==(const LLNetworkData& data) const; + /*virtual*/ void copy(const LLNetworkData& data); + + void setColor(const LLColor4& color) { mColor = color; mColor.clamp(); } + void setRadius(F32 radius) { mRadius = llclamp(radius, LIGHT_MIN_RADIUS, LIGHT_MAX_RADIUS); } + void setFalloff(F32 falloff) { mFalloff = llclamp(falloff, LIGHT_MIN_FALLOFF, LIGHT_MAX_FALLOFF); } + void setCutoff(F32 cutoff) { mCutoff = llclamp(cutoff, LIGHT_MIN_CUTOFF, LIGHT_MAX_CUTOFF); } + + LLColor4 getColor() const { return mColor; } + F32 getRadius() const { return mRadius; } + F32 getFalloff() const { return mFalloff; } + F32 getCutoff() const { return mCutoff; } +}; + +//------------------------------------------------- +// This structure is also used in the part of the +// code that creates new flexible objects. +//------------------------------------------------- + +// These were made into enums so that they could be used as fixed size +// array bounds. +enum EFlexibleObjectConst +{ + // "Softness" => [0,3], increments of 1 + // Represents powers of 2: 0 -> 1, 3 -> 8 + FLEXIBLE_OBJECT_MIN_SECTIONS = 0, + FLEXIBLE_OBJECT_DEFAULT_NUM_SECTIONS = 2, + FLEXIBLE_OBJECT_MAX_SECTIONS = 3 +}; + +// "Tension" => [0,10], increments of 0.1 +extern const F32 FLEXIBLE_OBJECT_MIN_TENSION; +extern const F32 FLEXIBLE_OBJECT_DEFAULT_TENSION; +extern const F32 FLEXIBLE_OBJECT_MAX_TENSION; + +// "Drag" => [0,10], increments of 0.1 +extern const F32 FLEXIBLE_OBJECT_MIN_AIR_FRICTION; +extern const F32 FLEXIBLE_OBJECT_DEFAULT_AIR_FRICTION; +extern const F32 FLEXIBLE_OBJECT_MAX_AIR_FRICTION; + +// "Gravity" = [-10,10], increments of 0.1 +extern const F32 FLEXIBLE_OBJECT_MIN_GRAVITY; +extern const F32 FLEXIBLE_OBJECT_DEFAULT_GRAVITY; +extern const F32 FLEXIBLE_OBJECT_MAX_GRAVITY; + +// "Wind" = [0,10], increments of 0.1 +extern const F32 FLEXIBLE_OBJECT_MIN_WIND_SENSITIVITY; +extern const F32 FLEXIBLE_OBJECT_DEFAULT_WIND_SENSITIVITY; +extern const F32 FLEXIBLE_OBJECT_MAX_WIND_SENSITIVITY; + +extern const F32 FLEXIBLE_OBJECT_MAX_INTERNAL_TENSION_FORCE; + +extern const F32 FLEXIBLE_OBJECT_DEFAULT_LENGTH; +extern const BOOL FLEXIBLE_OBJECT_DEFAULT_USING_COLLISION_SPHERE; +extern const BOOL FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE; + + +class LLFlexibleObjectData : public LLNetworkData +{ +protected: + S32 mSimulateLOD; // 2^n = number of simulated sections + F32 mGravity; + F32 mAirFriction; // higher is more stable, but too much looks like it's underwater + F32 mWindSensitivity; // interacts with tension, air friction, and gravity + F32 mTension; //interacts in complex ways with other parameters + LLVector3 mUserForce; // custom user-defined force vector + //BOOL mUsingCollisionSphere; + //BOOL mRenderingCollisionSphere; + +public: + void setSimulateLOD(S32 lod) { mSimulateLOD = llclamp(lod, (S32)FLEXIBLE_OBJECT_MIN_SECTIONS, (S32)FLEXIBLE_OBJECT_MAX_SECTIONS); } + void setGravity(F32 gravity) { mGravity = llclamp(gravity, FLEXIBLE_OBJECT_MIN_GRAVITY, FLEXIBLE_OBJECT_MAX_GRAVITY); } + void setAirFriction(F32 friction) { mAirFriction = llclamp(friction, FLEXIBLE_OBJECT_MIN_AIR_FRICTION, FLEXIBLE_OBJECT_MAX_AIR_FRICTION); } + void setWindSensitivity(F32 wind) { mWindSensitivity = llclamp(wind, FLEXIBLE_OBJECT_MIN_WIND_SENSITIVITY, FLEXIBLE_OBJECT_MAX_WIND_SENSITIVITY); } + void setTension(F32 tension) { mTension = llclamp(tension, FLEXIBLE_OBJECT_MIN_TENSION, FLEXIBLE_OBJECT_MAX_TENSION); } + void setUserForce(LLVector3 &force) { mUserForce = force; } + + S32 getSimulateLOD() const { return mSimulateLOD; } + F32 getGravity() const { return mGravity; } + F32 getAirFriction() const { return mAirFriction; } + F32 getWindSensitivity() const { return mWindSensitivity; } + F32 getTension() const { return mTension; } + LLVector3 getUserForce() const { return mUserForce; } + + //------ the constructor for the structure ------------ + LLFlexibleObjectData(); + BOOL pack(LLDataPacker &dp) const; + BOOL unpack(LLDataPacker &dp); + bool operator==(const LLNetworkData& data) const; + void copy(const LLNetworkData& data); +};// end of attributes structure + +class LLPrimitive : public LLXform +{ +public: + LLPrimitive(); + virtual ~LLPrimitive(); + + static LLPrimitive *createPrimitive(LLPCode p_code); + void init(LLPCode p_code); + + void setPCode(const LLPCode pcode); + const LLVolume *getVolumeConst() const { return mVolumep; } // HACK for Windoze confusion about ostream operator in LLVolume + LLVolume *getVolume() const { return mVolumep; } + virtual BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false); + + // Modify texture entry properties + inline BOOL validTE(const U8 te_num) const; + const LLTextureEntry *getTE(const U8 te_num) const; + + virtual void setNumTEs(const U8 num_tes); + virtual void setAllTETextures(const LLUUID &tex_id); + virtual void setTE(const U8 index, const LLTextureEntry &te); + virtual S32 setTEColor(const U8 te, const LLColor4 &color); + virtual S32 setTEColor(const U8 te, const LLColor3 &color); + virtual S32 setTEAlpha(const U8 te, const F32 alpha); + virtual S32 setTETexture(const U8 te, const LLUUID &tex_id); + virtual S32 setTEScale (const U8 te, const F32 s, const F32 t); + virtual S32 setTEScaleS(const U8 te, const F32 s); + virtual S32 setTEScaleT(const U8 te, const F32 t); + virtual S32 setTEOffset (const U8 te, const F32 s, const F32 t); + virtual S32 setTEOffsetS(const U8 te, const F32 s); + virtual S32 setTEOffsetT(const U8 te, const F32 t); + virtual S32 setTERotation(const U8 te, const F32 r); + virtual S32 setTEBumpShinyFullbright(const U8 te, const U8 bump); + virtual S32 setTEBumpShiny(const U8 te, const U8 bump); + virtual S32 setTEMediaTexGen(const U8 te, const U8 media); + virtual S32 setTEBumpmap(const U8 te, const U8 bump); + virtual S32 setTETexGen(const U8 te, const U8 texgen); + virtual S32 setTEShiny(const U8 te, const U8 shiny); + virtual S32 setTEFullbright(const U8 te, const U8 fullbright); + virtual S32 setTEMediaFlags(const U8 te, const U8 flags); + virtual BOOL setMaterial(const U8 material); // returns TRUE if material changed + + void setTEArrays(const U8 size, + const LLUUID* image_ids, + const F32* scale_s, + const F32* scale_t); + void copyTEs(const LLPrimitive *primitive); + S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const; + S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type); + BOOL packTEMessage(LLMessageSystem *mesgsys) const; + BOOL packTEMessage(LLDataPacker &dp) const; + S32 unpackTEMessage(LLMessageSystem *mesgsys, char *block_name); + S32 unpackTEMessage(LLMessageSystem *mesgsys, char *block_name, const S32 block_num); // Variable num of blocks + BOOL unpackTEMessage(LLDataPacker &dp); + +#ifdef CHECK_FOR_FINITE + inline void setPosition(const LLVector3& pos); + inline void setPosition(const F32 x, const F32 y, const F32 z); + inline void addPosition(const LLVector3& pos); + + inline void setAngularVelocity(const LLVector3& avel); + inline void setAngularVelocity(const F32 x, const F32 y, const F32 z); + inline void setVelocity(const LLVector3& vel); + inline void setVelocity(const F32 x, const F32 y, const F32 z); + inline void setVelocityX(const F32 x); + inline void setVelocityY(const F32 y); + inline void setVelocityZ(const F32 z); + inline void addVelocity(const LLVector3& vel); + inline void setAcceleration(const LLVector3& accel); + inline void setAcceleration(const F32 x, const F32 y, const F32 z); +#else + // Don't override the base LLXForm operators. + // Special case for setPosition. If not check-for-finite, fall through to LLXform method. + // void setPosition(F32 x, F32 y, F32 z) + // void setPosition(LLVector3) + + void setAngularVelocity(const LLVector3& avel) { mAngularVelocity = avel; } + void setAngularVelocity(const F32 x, const F32 y, const F32 z) { mAngularVelocity.setVec(x,y,z); } + void setVelocity(const LLVector3& vel) { mVelocity = vel; } + void setVelocity(const F32 x, const F32 y, const F32 z) { mVelocity.setVec(x,y,z); } + void setVelocityX(const F32 x) { mVelocity.mV[VX] = x; } + void setVelocityY(const F32 y) { mVelocity.mV[VY] = y; } + void setVelocityZ(const F32 z) { mVelocity.mV[VZ] = z; } + void addVelocity(const LLVector3& vel) { mVelocity += vel; } + void setAcceleration(const LLVector3& accel) { mAcceleration = accel; } + void setAcceleration(const F32 x, const F32 y, const F32 z) { mAcceleration.setVec(x,y,z); } +#endif + + const LLPCode getPCode() const { return mPrimitiveCode; } + const char * getPCodeString() const { return pCodeToString(mPrimitiveCode); } + const LLVector3& getAngularVelocity() const { return mAngularVelocity; } + const LLVector3& getVelocity() const { return mVelocity; } + const LLVector3& getAcceleration() const { return mAcceleration; } + const U8 getNumTEs() const { return mNumTEs; } + + const U8 getMaterial() const { return mMaterial; } + + void setVolumeType(const U8 code); + U8 getVolumeType(); + + void setTextureList(LLTextureEntry *listp); + + inline BOOL isAvatar() const; + + static const char *pCodeToString(const LLPCode pcode); + static LLPCode legacyToPCode(const U8 legacy); + static U8 pCodeToLegacy(const LLPCode pcode); + + inline static BOOL isPrimitive(const LLPCode pcode); + inline static BOOL isApp(const LLPCode pcode); + +protected: + LLPCode mPrimitiveCode; // Primitive code + LLVector3 mVelocity; // how fast are we moving? + LLVector3 mAcceleration; // are we under constant acceleration? + LLVector3 mAngularVelocity; // angular velocity + LLPointer<LLVolume> mVolumep; + LLTextureEntry *mTextureList; // list of texture GUIDs, scales, offsets + U8 mMaterial; // Material code + U8 mNumTEs; // # of faces on the primitve +}; + +inline BOOL LLPrimitive::isAvatar() const +{ + return mPrimitiveCode == LL_PCODE_LEGACY_AVATAR; +} + +// static +inline BOOL LLPrimitive::isPrimitive(const LLPCode pcode) +{ + LLPCode base_type = pcode & LL_PCODE_BASE_MASK; + + if (base_type && (base_type < LL_PCODE_APP)) + { + return TRUE; + } + return FALSE; +} + +// static +inline BOOL LLPrimitive::isApp(const LLPCode pcode) +{ + LLPCode base_type = pcode & LL_PCODE_BASE_MASK; + + return (base_type == LL_PCODE_APP); +} + + +#ifdef CHECK_FOR_FINITE +// Special case for setPosition. If not check-for-finite, fall through to LLXform method. +void LLPrimitive::setPosition(const F32 x, const F32 y, const F32 z) +{ + if (llfinite(x) && llfinite(y) && llfinite(z)) + { + LLXform::setPosition(x, y, z); + } + else + { + llerrs << "Non Finite in LLPrimitive::setPosition(x,y,z) for " << pCodeToString(mPrimitiveCode) << llendl; + } +} + +// Special case for setPosition. If not check-for-finite, fall through to LLXform method. +void LLPrimitive::setPosition(const LLVector3& pos) +{ + if (pos.isFinite()) + { + LLXform::setPosition(pos); + } + else + { + llerrs << "Non Finite in LLPrimitive::setPosition(LLVector3) for " << pCodeToString(mPrimitiveCode) << llendl; + } +} + +void LLPrimitive::setAngularVelocity(const LLVector3& avel) +{ + if (avel.isFinite()) + { + mAngularVelocity = avel; + } + else + { + llerror("Non Finite in LLPrimitive::setAngularVelocity", 0); + } +} + +void LLPrimitive::setAngularVelocity(const F32 x, const F32 y, const F32 z) +{ + if (llfinite(x) && llfinite(y) && llfinite(z)) + { + mAngularVelocity.setVec(x,y,z); + } + else + { + llerror("Non Finite in LLPrimitive::setAngularVelocity", 0); + } +} + +void LLPrimitive::setVelocity(const LLVector3& vel) +{ + if (vel.isFinite()) + { + mVelocity = vel; + } + else + { + llerrs << "Non Finite in LLPrimitive::setVelocity(LLVector3) for " << pCodeToString(mPrimitiveCode) << llendl; + } +} + +void LLPrimitive::setVelocity(const F32 x, const F32 y, const F32 z) +{ + if (llfinite(x) && llfinite(y) && llfinite(z)) + { + mVelocity.setVec(x,y,z); + } + else + { + llerrs << "Non Finite in LLPrimitive::setVelocity(F32,F32,F32) for " << pCodeToString(mPrimitiveCode) << llendl; + } +} + +void LLPrimitive::setVelocityX(const F32 x) +{ + if (llfinite(x)) + { + mVelocity.mV[VX] = x; + } + else + { + llerror("Non Finite in LLPrimitive::setVelocityX", 0); + } +} + +void LLPrimitive::setVelocityY(const F32 y) +{ + if (llfinite(y)) + { + mVelocity.mV[VY] = y; + } + else + { + llerror("Non Finite in LLPrimitive::setVelocityY", 0); + } +} + +void LLPrimitive::setVelocityZ(const F32 z) +{ + if (llfinite(z)) + { + mVelocity.mV[VZ] = z; + } + else + { + llerror("Non Finite in LLPrimitive::setVelocityZ", 0); + } +} + +void LLPrimitive::addVelocity(const LLVector3& vel) +{ + if (vel.isFinite()) + { + mVelocity += vel; + } + else + { + llerror("Non Finite in LLPrimitive::addVelocity", 0); + } +} + +void LLPrimitive::setAcceleration(const LLVector3& accel) +{ + if (accel.isFinite()) + { + mAcceleration = accel; + } + else + { + llerrs << "Non Finite in LLPrimitive::setAcceleration(LLVector3) for " << pCodeToString(mPrimitiveCode) << llendl; + } +} + +void LLPrimitive::setAcceleration(const F32 x, const F32 y, const F32 z) +{ + if (llfinite(x) && llfinite(y) && llfinite(z)) + { + mAcceleration.setVec(x,y,z); + } + else + { + llerrs << "Non Finite in LLPrimitive::setAcceleration(F32,F32,F32) for " << pCodeToString(mPrimitiveCode) << llendl; + } +} +#endif // CHECK_FOR_FINITE + +inline BOOL LLPrimitive::validTE(const U8 te_num) const +{ + return (mNumTEs && te_num < mNumTEs); +} + +#endif + diff --git a/indra/llprimitive/lltextureanim.cpp b/indra/llprimitive/lltextureanim.cpp new file mode 100644 index 0000000000..3e2c80e782 --- /dev/null +++ b/indra/llprimitive/lltextureanim.cpp @@ -0,0 +1,221 @@ +/** + * @file lltextureanim.cpp + * @brief LLTextureAnim base class + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "linden_common.h" + +#include "lltextureanim.h" +#include "message.h" +#include "lldatapacker.h" + +const S32 TA_BLOCK_SIZE = 16; + +LLTextureAnim::LLTextureAnim() +{ + reset(); +} + + +LLTextureAnim::~LLTextureAnim() +{ +} + + +void LLTextureAnim::reset() +{ + mMode = 0; + mFace = -1; + mSizeX = 4; + mSizeY = 4; + mStart = 0.f; + mLength = 0.f; + mRate = 1.f; +} + +BOOL LLTextureAnim::equals(const LLTextureAnim &other) const +{ + if (mMode != other.mMode) + { + return FALSE; + } + if (mFace != other.mFace) + { + return FALSE; + } + if (mSizeX != other.mSizeX) + { + return FALSE; + } + if (mSizeY != other.mSizeY) + { + return FALSE; + } + if (mStart != other.mStart) + { + return FALSE; + } + if (mLength != other.mLength) + { + return FALSE; + } + if (mRate != other.mRate) + { + return FALSE; + } + + return TRUE; +} +void LLTextureAnim::packTAMessage(LLMessageSystem *mesgsys) const +{ + U8 data[TA_BLOCK_SIZE]; + data[0] = mMode; + data[1] = mFace; + data[2] = mSizeX; + data[3] = mSizeY; + htonmemcpy(data + 4, &mStart, MVT_F32, sizeof(F32)); + htonmemcpy(data + 8, &mLength, MVT_F32, sizeof(F32)); + htonmemcpy(data + 12, &mRate, MVT_F32, sizeof(F32)); + + mesgsys->addBinaryDataFast(_PREHASH_TextureAnim, data, TA_BLOCK_SIZE); +} + + +void LLTextureAnim::packTAMessage(LLDataPacker &dp) const +{ + U8 data[TA_BLOCK_SIZE]; + data[0] = mMode; + data[1] = mFace; + data[2] = mSizeX; + data[3] = mSizeY; + htonmemcpy(data + 4, &mStart, MVT_F32, sizeof(F32)); + htonmemcpy(data + 8, &mLength, MVT_F32, sizeof(F32)); + htonmemcpy(data + 12, &mRate, MVT_F32, sizeof(F32)); + + dp.packBinaryData(data, TA_BLOCK_SIZE, "TextureAnimation"); +} + + +void LLTextureAnim::unpackTAMessage(LLMessageSystem *mesgsys, const S32 block_num) +{ + S32 size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureAnim); + + if (size != TA_BLOCK_SIZE) + { + if (size) + { + llwarns << "Bad size " << size << " for TA block, ignoring." << llendl; + } + mMode = 0; + return; + } + + U8 data[TA_BLOCK_SIZE]; + mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureAnim, data, TA_BLOCK_SIZE, block_num); + + mMode = data[0]; + mFace = data[1]; + if (mMode & LLTextureAnim::SMOOTH) + { + mSizeX = llmax((U8)0, data[2]); + mSizeY = llmax((U8)0, data[3]); + } + else + { + mSizeX = llmax((U8)1, data[2]); + mSizeY = llmax((U8)1, data[3]); + } + htonmemcpy(&mStart, data + 4, MVT_F32, sizeof(F32)); + htonmemcpy(&mLength, data + 8, MVT_F32, sizeof(F32)); + htonmemcpy(&mRate, data + 12, MVT_F32, sizeof(F32)); +} + +void LLTextureAnim::unpackTAMessage(LLDataPacker &dp) +{ + S32 size; + U8 data[TA_BLOCK_SIZE]; + dp.unpackBinaryData(data, size, "TextureAnimation"); + if (size != TA_BLOCK_SIZE) + { + if (size) + { + llwarns << "Bad size " << size << " for TA block, ignoring." << llendl; + } + mMode = 0; + return; + } + + mMode = data[0]; + mFace = data[1]; + mSizeX = llmax((U8)1, data[2]); + mSizeY = llmax((U8)1, data[3]); + htonmemcpy(&mStart, data + 4, MVT_F32, sizeof(F32)); + htonmemcpy(&mLength, data + 8, MVT_F32, sizeof(F32)); + htonmemcpy(&mRate, data + 12, MVT_F32, sizeof(F32)); +} + +LLSD LLTextureAnim::asLLSD() const +{ + LLSD sd; + sd["mode"] = mMode; + sd["face"] = mFace; + sd["sizeX"] = mSizeX; + sd["sizeY"] = mSizeY; + sd["start"] = mStart; + sd["length"] = mLength; + sd["rate"] = mRate; + return sd; +} + +bool LLTextureAnim::fromLLSD(LLSD& sd) +{ + const char *w; + w = "mode"; + if (sd.has(w)) + { + mMode = (U8)sd[w].asInteger(); + } else goto fail; + + w = "face"; + if (sd.has(w)) + { + mFace = (S8)sd[w].asInteger(); + } else goto fail; + + w = "sizeX"; + if (sd.has(w)) + { + mSizeX = (U8)sd[w].asInteger(); + } else goto fail; + + w = "sizeY"; + if (sd.has(w)) + { + mSizeY = (U8)sd[w].asInteger(); + } else goto fail; + + w = "start"; + if (sd.has(w)) + { + mStart = (F32)sd[w].asReal(); + } else goto fail; + + w = "length"; + if (sd.has(w)) + { + mLength = (F32)sd[w].asReal(); + } else goto fail; + + w = "rate"; + if (sd.has(w)) + { + mRate = (F32)sd[w].asReal(); + } else goto fail; + + return true; +fail: + return false; +} diff --git a/indra/llprimitive/lltextureanim.h b/indra/llprimitive/lltextureanim.h new file mode 100644 index 0000000000..db15642563 --- /dev/null +++ b/indra/llprimitive/lltextureanim.h @@ -0,0 +1,54 @@ +/** + * @file lltextureanim.h + * @brief LLTextureAnim base class + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_LLTEXTUREANIM_H +#define LL_LLTEXTUREANIM_H + +#include "stdtypes.h" +#include "llsd.h" + +class LLMessageSystem; +class LLDataPacker; + +class LLTextureAnim +{ +public: + LLTextureAnim(); + virtual ~LLTextureAnim(); + + virtual void reset(); + void packTAMessage(LLMessageSystem *mesgsys) const; + void packTAMessage(LLDataPacker &dp) const; + void unpackTAMessage(LLMessageSystem *mesgsys, const S32 block_num); + void unpackTAMessage(LLDataPacker &dp); + BOOL equals(const LLTextureAnim &other) const; + LLSD asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); + + enum + { + ON = 0x01, + LOOP = 0x02, + REVERSE = 0x04, + PING_PONG = 0x08, + SMOOTH = 0x10, + ROTATE = 0x20, + SCALE = 0x40, + }; + +public: + U8 mMode; + S8 mFace; + U8 mSizeX; + U8 mSizeY; + F32 mStart; + F32 mLength; + F32 mRate; // Rate in frames per second. +}; +#endif diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp new file mode 100644 index 0000000000..86952dfdb5 --- /dev/null +++ b/indra/llprimitive/lltextureentry.cpp @@ -0,0 +1,348 @@ +/** + * @file lltextureentry.cpp + * @brief LLTextureEntry base class + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "linden_common.h" + +#include "lltextureentry.h" +#include "llsdutil.h" + +const U8 DEFAULT_BUMP_CODE = 0; // no bump or shininess + +const LLTextureEntry LLTextureEntry::null; + +//=============================================================== +LLTextureEntry::LLTextureEntry() +{ + init(LLUUID::null,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE); +} + +LLTextureEntry::LLTextureEntry(const LLUUID& tex_id) +{ + init(tex_id,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE); +} + +LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs) +{ + mID = rhs.mID; + mScaleS = rhs.mScaleS; + mScaleT = rhs.mScaleT; + mOffsetS = rhs.mOffsetS; + mOffsetT = rhs.mOffsetT; + mRotation = rhs.mRotation; + mColor = rhs.mColor; + mBump = rhs.mBump; + mMediaFlags = rhs.mMediaFlags; +} + +LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs) +{ + if (this != &rhs) + { + mID = rhs.mID; + mScaleS = rhs.mScaleS; + mScaleT = rhs.mScaleT; + mOffsetS = rhs.mOffsetS; + mOffsetT = rhs.mOffsetT; + mRotation = rhs.mRotation; + mColor = rhs.mColor; + mBump = rhs.mBump; + mMediaFlags = rhs.mMediaFlags; + } + + return *this; +} + +void LLTextureEntry::init(const LLUUID& tex_id, F32 scale_s, F32 scale_t, F32 offset_s, F32 offset_t, F32 rotation, U8 bump) +{ + setID(tex_id); + + mScaleS = scale_s; + mScaleT = scale_t; + mOffsetS = offset_s; + mOffsetT = offset_t; + mRotation = rotation; + mBump = bump; + mMediaFlags = 0x0; + + setColor(LLColor4(1.f, 1.f, 1.f, 1.f)); +} + +LLTextureEntry::~LLTextureEntry() +{ +} + +bool LLTextureEntry::operator!=(const LLTextureEntry &rhs) const +{ + if (mID != rhs.mID) return(true); + if (mScaleS != rhs.mScaleS) return(true); + if (mScaleT != rhs.mScaleT) return(true); + if (mOffsetS != rhs.mOffsetS) return(true); + if (mOffsetT != rhs.mOffsetT) return(true); + if (mRotation != rhs.mRotation) return(true); + if (mColor != rhs.mColor) return (true); + if (mBump != rhs.mBump) return (true); + if (mMediaFlags != rhs.mMediaFlags) return true; + return(false); +} + +bool LLTextureEntry::operator==(const LLTextureEntry &rhs) const +{ + if (mID != rhs.mID) return(false); + if (mScaleS != rhs.mScaleS) return(false); + if (mScaleT != rhs.mScaleT) return(false); + if (mOffsetS != rhs.mOffsetS) return(false); + if (mOffsetT != rhs.mOffsetT) return(false); + if (mRotation != rhs.mRotation) return(false); + if (mColor != rhs.mColor) return (false); + if (mBump != rhs.mBump) return (false); + if (mMediaFlags != rhs.mMediaFlags) return false; + return(true); +} + +LLSD LLTextureEntry::asLLSD() const +{ + LLSD sd; + + sd["imageid"] = getID(); + sd["colors"] = ll_sd_from_color4(getColor()); + sd["scales"] = mScaleS; + sd["scalet"] = mScaleT; + sd["offsets"] = mOffsetS; + sd["offsett"] = mOffsetT; + sd["imagerot"] = getRotation(); + sd["bump"] = getBumpShiny(); + sd["fullbright"] = getFullbright(); + sd["media_flags"] = getMediaTexGen(); + + return sd; +} + +bool LLTextureEntry::fromLLSD(LLSD& sd) +{ + const char *w, *x; + w = "imageid"; + if (sd.has(w)) + { + setID( sd[w] ); + } else goto fail; + w = "colors"; + if (sd.has(w)) + { + setColor( ll_color4_from_sd(sd["colors"]) ); + } else goto fail; + w = "scales"; + x = "scalet"; + if (sd.has(w) && sd.has(x)) + { + setScale( (F32)sd[w].asReal(), (F32)sd[x].asReal() ); + } else goto fail; + w = "offsets"; + x = "offsett"; + if (sd.has(w) && sd.has(x)) + { + setOffset( (F32)sd[w].asReal(), (F32)sd[x].asReal() ); + } else goto fail; + w = "imagerot"; + if (sd.has(w)) + { + setRotation( (F32)sd[w].asReal() ); + } else goto fail; + w = "bump"; + if (sd.has(w)) + { + setBumpShiny( sd[w].asInteger() ); + } else goto fail; + w = "fullbright"; + if (sd.has(w)) + { + setFullbright( sd[w].asInteger() ); + } else goto fail; + w = "media_flags"; + if (sd.has(w)) + { + setMediaTexGen( sd[w].asInteger() ); + } else goto fail; + + return true; +fail: + return false; +} + +S32 LLTextureEntry::setID(const LLUUID &tex_id) +{ + if (mID != tex_id) + { + mID = tex_id; + return TEM_CHANGE_TEXTURE; + } + return 0; +} + +S32 LLTextureEntry::setScale(F32 s, F32 t) +{ + S32 retval = 0; + + if ( (mScaleS != s) + ||(mScaleT != t)) + { + mScaleS = s; + mScaleT = t; + + retval = TEM_CHANGE_TEXTURE; + } + return retval; +} + +S32 LLTextureEntry::setColor(const LLColor4 &color) +{ + if (mColor != color) + { + mColor = color; + return TEM_CHANGE_COLOR; + } + return 0; +} + +S32 LLTextureEntry::setColor(const LLColor3 &color) +{ + if (mColor != color) + { + // This preserves alpha. + mColor.setVec(color); + return TEM_CHANGE_COLOR; + } + return 0; +} + +S32 LLTextureEntry::setAlpha(const F32 alpha) +{ + if (mColor.mV[VW] != alpha) + { + mColor.mV[VW] = alpha; + return TEM_CHANGE_COLOR; + } + return 0; +} + +S32 LLTextureEntry::setOffset(F32 s, F32 t) +{ + S32 retval = 0; + + if ( (mOffsetS != s) + ||(mOffsetT != t)) + { + mOffsetS = s; + mOffsetT = t; + + retval = TEM_CHANGE_TEXTURE; + } + return retval; +} + +S32 LLTextureEntry::setRotation(F32 theta) +{ + if (mRotation != theta) + { + mRotation = theta; + return TEM_CHANGE_TEXTURE; + } + return 0; +} + +S32 LLTextureEntry::setBumpShinyFullbright(U8 bump) +{ + if (mBump != bump) + { + mBump = bump; + return TEM_CHANGE_TEXTURE; + } + return 0; +} + +S32 LLTextureEntry::setMediaTexGen(U8 media) +{ + if (mMediaFlags != media) + { + mMediaFlags = media; + return TEM_CHANGE_TEXTURE; + } + return 0; +} + +S32 LLTextureEntry::setBumpmap(U8 bump) +{ + bump &= TEM_BUMP_MASK; + if (getBumpmap() != bump) + { + mBump &= ~TEM_BUMP_MASK; + mBump |= bump; + return TEM_CHANGE_TEXTURE; + } + return 0; +} + +S32 LLTextureEntry::setFullbright(U8 fullbright) +{ + fullbright &= TEM_FULLBRIGHT_MASK; + if (getFullbright() != fullbright) + { + mBump &= ~(TEM_FULLBRIGHT_MASK<<TEM_FULLBRIGHT_SHIFT); + mBump |= fullbright << TEM_FULLBRIGHT_SHIFT; + return TEM_CHANGE_TEXTURE; + } + return 0; +} + +S32 LLTextureEntry::setShiny(U8 shiny) +{ + shiny &= TEM_SHINY_MASK; + if (getShiny() != shiny) + { + mBump &= ~(TEM_SHINY_MASK<<TEM_SHINY_SHIFT); + mBump |= shiny << TEM_SHINY_SHIFT; + return TEM_CHANGE_TEXTURE; + } + return 0; +} + +S32 LLTextureEntry::setBumpShiny(U8 bump_shiny) +{ + bump_shiny &= TEM_BUMP_SHINY_MASK; + if (getBumpShiny() != bump_shiny) + { + mBump &= ~TEM_BUMP_SHINY_MASK; + mBump |= bump_shiny; + return TEM_CHANGE_TEXTURE; + } + return 0; +} + +S32 LLTextureEntry::setMediaFlags(U8 media_flags) +{ + media_flags &= TEM_MEDIA_MASK; + if (getMediaFlags() != media_flags) + { + mMediaFlags &= ~TEM_MEDIA_MASK; + mMediaFlags |= media_flags; + return TEM_CHANGE_TEXTURE; + } + return 0; +} + +S32 LLTextureEntry::setTexGen(U8 tex_gen) +{ + tex_gen &= TEM_TEX_GEN_MASK; + if (getTexGen() != tex_gen) + { + mMediaFlags &= ~TEM_TEX_GEN_MASK; + mMediaFlags |= tex_gen; + return TEM_CHANGE_TEXTURE; + } + return 0; +} + diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h new file mode 100644 index 0000000000..b9558a159a --- /dev/null +++ b/indra/llprimitive/lltextureentry.h @@ -0,0 +1,126 @@ +/** + * @file lltextureentry.h + * @brief LLTextureEntry base class + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_LLTEXTUREENTRY_H +#define LL_LLTEXTUREENTRY_H + +#include "lluuid.h" +#include "v4color.h" +#include "llsd.h" + +const S32 TEM_CHANGE_COLOR = 0x1; +const S32 TEM_CHANGE_TEXTURE = 0x2; +const S32 TEM_INVALID = 0x4; + +const S32 TEM_BUMPMAP_COUNT = 32; + +// The Bump Shiny Fullbright values are bits in an eight bit field: +// +----------+ +// | SSFBBBBB | S = Shiny, F = Fullbright, B = Bumpmap +// | 76543210 | +// +----------+ +const S32 TEM_BUMP_MASK = 0x1f; // 5 bits +const S32 TEM_FULLBRIGHT_MASK = 0x01; // 1 bit +const S32 TEM_SHINY_MASK = 0x03; // 2 bits +const S32 TEM_BUMP_SHINY_MASK = (0xc0 | 0x1f); +const S32 TEM_FULLBRIGHT_SHIFT = 5; +const S32 TEM_SHINY_SHIFT = 6; + +// The Media Tex Gen values are bits in a bit field: +// +----------+ +// | .....TTM | M = Media Flags (web page), T = LLTextureEntry::eTexGen, . = unused +// | 76543210 | +// +----------+ +const S32 TEM_MEDIA_MASK = 0x01; +const S32 TEM_TEX_GEN_MASK = 0x06; +const S32 TEM_TEX_GEN_SHIFT = 1; + + +class LLTextureEntry +{ +public: + + typedef enum e_texgen + { + TEX_GEN_DEFAULT = 0x00, + TEX_GEN_PLANAR = 0x02, + TEX_GEN_SPHERICAL = 0x04, + TEX_GEN_CYLINDRICAL = 0x06 + } eTexGen; + + LLTextureEntry(); + LLTextureEntry(const LLUUID& tex_id); + LLTextureEntry(const LLTextureEntry &rhs); + + LLTextureEntry &operator=(const LLTextureEntry &rhs); + ~LLTextureEntry(); + + bool operator==(const LLTextureEntry &rhs) const; + bool operator!=(const LLTextureEntry &rhs) const; + + LLSD asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); + + void init(const LLUUID& tex_id, F32 scale_s, F32 scale_t, F32 offset_s, F32 offset_t, F32 rotation, U8 bump); + + // These return a TEM_ flag from above to indicate if something changed. + S32 setID (const LLUUID &tex_id); + S32 setColor(const LLColor4 &color); + S32 setColor(const LLColor3 &color); + S32 setAlpha(const F32 alpha); + S32 setScale(F32 s, F32 t); + S32 setOffset(F32 s, F32 t); + S32 setRotation(F32 theta); + + S32 setBumpmap(U8 bump); + S32 setFullbright(U8 bump); + S32 setShiny(U8 bump); + S32 setBumpShiny(U8 bump); + S32 setBumpShinyFullbright(U8 bump); + + S32 setMediaFlags(U8 media_flags); + S32 setTexGen(U8 texGen); + S32 setMediaTexGen(U8 media); + + const LLUUID &getID() const { return mID; } + const LLColor4 &getColor() const { return mColor; } + void getScale(F32 *s, F32 *t) const { *s = mScaleS; *t = mScaleT; } + void getOffset(F32 *s, F32 *t) const { *s = mOffsetS; *t = mOffsetT; } + F32 getRotation() const { return mRotation; } + void getRotation(F32 *theta) const { *theta = mRotation; } + + U8 getBumpmap() const { return mBump & TEM_BUMP_MASK; } + U8 getFullbright() const { return (mBump>>TEM_FULLBRIGHT_SHIFT) & TEM_FULLBRIGHT_MASK; } + U8 getShiny() const { return (mBump>>TEM_SHINY_SHIFT) & TEM_SHINY_MASK; } + U8 getBumpShiny() const { return mBump & TEM_BUMP_SHINY_MASK; } + U8 getBumpShinyFullbright() const { return mBump; } + + U8 getMediaFlags() const { return mMediaFlags & TEM_MEDIA_MASK; } + U8 getTexGen() const { return mMediaFlags & TEM_TEX_GEN_MASK; } + U8 getMediaTexGen() const { return mMediaFlags; } + + // Media flags + enum { MF_NONE = 0x0, MF_WEB_PAGE = 0x1 }; + +public: + F32 mScaleS; // S, T offset + F32 mScaleT; // S, T offset + F32 mOffsetS; // S, T offset + F32 mOffsetT; // S, T offset + F32 mRotation; // anti-clockwise rotation in rad about the bottom left corner + + static const LLTextureEntry null; +protected: + LLUUID mID; // Texture GUID + LLColor4 mColor; + U8 mBump; // Bump map, shiny, and fullbright + U8 mMediaFlags; // replace with web page, movie, etc. +}; + +#endif diff --git a/indra/llprimitive/lltreeparams.cpp b/indra/llprimitive/lltreeparams.cpp new file mode 100644 index 0000000000..ca3de36630 --- /dev/null +++ b/indra/llprimitive/lltreeparams.cpp @@ -0,0 +1,187 @@ +/** + * @file lltreeparams.cpp + * @brief implementation of the LLTreeParams class. + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +////////////////////////////////////////////////////////////////////// + +#include "linden_common.h" + +#include "llmath.h" + +#include "lltreeparams.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +LLTreeParams::LLTreeParams() +{ + +// llinfos << "TREE PARAMS INITIALIZED" << llendl; + // init to basic something or other... + mShape = SR_TEND_FLAME; + mLevels = 1; + mScale = 15; + mScaleV = 0; + + mBaseSize = 0.3f; + + mRatio = 0.015f; + mRatioPower = 1.3f; + + mLobes = 0; + mLobeDepth = .1f; + + mFlare = 1.2f; + mFlarePercentage = 0.1f; + mFlareRes = 3; + + //mAttractionUp = .5f; + + mBaseSplits = 0; + + mScale0 = 2.0; + mScaleV0 = 0.0; + + // level 0 + + // scaling + mLength[0] = 1.0f; + mLengthV[0] = 0; + mTaper[0] = 1.0f; + + // stem splits + mSegSplits[0] = 0.15f; + mSplitAngle[0] = 15.0f; + mSplitAngleV[0] = 10.0f; + + mVertices[0] = 5; + + // curvature + mCurveRes[0] = 4; + mCurve[0] = 0; + mCurveV[0] = 25; + mCurveBack[0] = 0; + + // level 1 + + // scaling + mLength[1] = .3f; + mLengthV[1] = 0.05f; + mTaper[1] = 1.0f; + + // angle params + mDownAngle[0] = 60.0f; + mDownAngleV[0] = 20.0f; + mRotate[0] = 140.0f; + mRotateV[0] = 0.0f; + mBranches[0] = 35; + + mVertices[1] = 3; + + // stem splits + mSplitAngle[1] = 0.0f; + mSplitAngleV[1] = 0.0f; + mSegSplits[1] = 0.0f; + + // curvature + mCurveRes[1] = 4; + mCurve[1] = 0; + mCurveV[1] = 0; + mCurveBack[1] = 40; + + // level 2 + mLength[2] = .6f; + mLengthV[2] = .1f; + mTaper[2] = 1; + + mDownAngle[1] = 30; + mDownAngleV[1] = 10; + mRotate[1] = 140; + mRotateV[1] = 0; + + mBranches[1] = 20; + mVertices[2] = 3; + + mSplitAngle[2] = 0; + mSplitAngleV[2] = 0; + mSegSplits[2] = 0; + + mCurveRes[2] = 3; + mCurve[2] = 10; + mCurveV[2] = 150; + mCurveBack[2] = 0; + + // level 3 + mLength[3] = .4f; + mLengthV[3] = 0; + mTaper[3] = 1; + + mDownAngle[2] = 45; + mDownAngleV[2] = 10; + mRotate[2] = 140; + mRotateV[2] = 0; + + mBranches[2] = 5; + mVertices[3] = 3; + + + mSplitAngle[3] = 0; + mSplitAngleV[3] = 0; + mSegSplits[3] = 0; + + mCurveRes[3] = 2; + mCurve[3] = 0; + mCurveV[3] = 0; + mCurveBack[3] = 0; + + mLeaves = 0; + mLeafScaleX = 1.0f; + mLeafScaleY = 1.0f; + + mLeafQuality = 1.25; +} + +LLTreeParams::~LLTreeParams() +{ + +} + +F32 LLTreeParams::ShapeRatio(EShapeRatio shape, F32 ratio) +{ + switch (shape) { + case (SR_CONICAL): + return (.2f + .8f * ratio); + case (SR_SPHERICAL): + return (.2f + .8f * sinf(F_PI*ratio)); + case (SR_HEMISPHERICAL): + return (.2f + .8f * sinf(.5*F_PI*ratio)); + case (SR_CYLINDRICAL): + return (1); + case (SR_TAPERED_CYLINDRICAL): + return (.5f + .5f * ratio); + case (SR_FLAME): + if (ratio <= .7f) { + return ratio/.7f; + } else { + return ((1 - ratio)/.3f); + } + case (SR_INVERSE_CONICAL): + return (1 - .8f * ratio); + case (SR_TEND_FLAME): + if (ratio <= .7) { + return (.5f + .5f*(ratio/.7f)); + } else { + return (.5f + .5f * (1 - ratio)/.3f); + } + case (SR_ENVELOPE): + return 1; + default: + return 1; + } +} diff --git a/indra/llprimitive/lltreeparams.h b/indra/llprimitive/lltreeparams.h new file mode 100644 index 0000000000..fa55f584e3 --- /dev/null +++ b/indra/llprimitive/lltreeparams.h @@ -0,0 +1,183 @@ +/** + * @file lltreeparams.h + * @brief Implementation of the LLTreeParams class + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_LLTREEPARAMS_H +#define LL_LLTREEPARAMS_H + +/* for information about formulas associated with each type + * check the Weber + Penn paper + */ +typedef enum EShapeRatio { SR_CONICAL, SR_SPHERICAL, SR_HEMISPHERICAL, + SR_CYLINDRICAL, SR_TAPERED_CYLINDRICAL, SR_FLAME, + SR_INVERSE_CONICAL, SR_TEND_FLAME, SR_ENVELOPE}; + +const U32 TREE_BLOCK_SIZE = 16; + +const U8 MAX_NUM_LEVELS = 4; + +class LLTreeParams +{ +public: + LLTreeParams(); + virtual ~LLTreeParams(); + + static F32 ShapeRatio(EShapeRatio shape, F32 ratio); + +public: + + // Variables with an asterick (*) cannot be modified without a re-instancing the + // trunk/branches + + // Variables with an exclamation point (!) should probably not be modified outside and instead + // be tied directly to the species + + // Variables with a tilde (~) should be tied to a range specified by the + // species type but still slightly controllable by the user + + // GENERAL + + //! determines length/radius of branches on tree -- ie: general 'shape' + EShapeRatio mShape; + + //! number of recursive branch levels...limit to MAX_NUM_LEVELS + U8 mLevels; + + //~ percentage of trunk at bottom without branches + F32 mBaseSize; + + //~ the general scale + variance of tree + F32 mScale, mScaleV; + + // general scale of tree + F32 mScale0, mScaleV0; + + + + // LOBING + + //*! number of peaks in the radial distance about the perimeter + U8 mLobes; + // even numbers = obvius symmetry ... use odd numbers + + //*! magnitude of the variations as a fraction of the radius + F32 mLobeDepth; + + + + // FLARE + + //*! causes exponential expansion near base of trunk + F32 mFlare; + // scales radius base by min 1 to '1 + flare' + + //*! percentage of the height of the trunk to flair -- likely less than baseSize + F32 mFlarePercentage; + + //*! number of cross sections to make for the flair + U8 mFlareRes; + + + + // LEAVES + + //~ number of leaves to make + U8 mLeaves; + + //! scale of the leaves + F32 mLeafScaleX, mLeafScaleY; + + // quality/density of leaves + F32 mLeafQuality; + + // several params don't have level 0 values + + // BRANCHES + + //~ angle away from parent + F32 mDownAngle[MAX_NUM_LEVELS - 1]; + F32 mDownAngleV[MAX_NUM_LEVELS - 1]; + + //~ rotation around parent + F32 mRotate[MAX_NUM_LEVELS - 1]; + F32 mRotateV[MAX_NUM_LEVELS - 1]; + + //~ num branches to spawn + U8 mBranches[MAX_NUM_LEVELS - 1]; + + //~ fractional length of branch. 1 = same length as parent branch + F32 mLength[MAX_NUM_LEVELS]; + F32 mLengthV[MAX_NUM_LEVELS]; + + //!~ ratio and ratiopower determine radius/length + F32 mRatio, mRatioPower; + + //*! taper of branches + F32 mTaper[MAX_NUM_LEVELS]; + // 0 - non-tapering cylinder + // 1 - taper to a point + // 2 - taper to a spherical end + // 3 - periodic tapering (concatenated spheres) + + //! SEG SPLITTING + U8 mBaseSplits; //! num segsplits at first curve cross section of trunk + F32 mSegSplits[MAX_NUM_LEVELS]; //~ splits per cross section. 1 = 1 split per section + F32 mSplitAngle[MAX_NUM_LEVELS]; //~ angle that splits go from parent (tempered by height) + F32 mSplitAngleV[MAX_NUM_LEVELS]; //~ variance of the splits + + // CURVE + F32 mCurve[MAX_NUM_LEVELS]; //* general, 1-axis, overall curve of branch + F32 mCurveV[MAX_NUM_LEVELS]; //* curve variance at each cross section from general overall curve + U8 mCurveRes[MAX_NUM_LEVELS]; //* number of cross sections for curve + F32 mCurveBack[MAX_NUM_LEVELS]; //* curveback is amount branch curves back towards + + // vertices per cross section + U8 mVertices[MAX_NUM_LEVELS]; + + // * no longer useful with pre-instanced branches + // specifies upward tendency of branches. + //F32 mAttractionUp; + // 1 = each branch will slightly go upwards by the end of the branch + // >1 = branches tend to go upwards earlier in their length + // pruning not implemented + // Prune parameters + //F32 mPruneRatio; + //F32 mPruneWidth, mPruneWidthPeak; + //F32 mPrunePowerLow, mPrunePowerHigh; + + + // NETWORK MESSAGE DATA + // Below is the outline for network messages regarding trees. + // The general idea is that a user would pick a general 'tree type' (the first variable) + // and then several 'open ended' variables like 'branchiness' and 'leafiness'. + // The effect that each of these general user variables would then affect the actual + // tree parameters (like # branches, # segsplits) in different ways depending on + // the tree type selected. Essentially, each tree type should have a formula + // that expands the 'leafiness' and 'branchiness' user variables into actual + // values for the tree parameters. + + // These formulas aren't made yet and will certainly require some tuning. The + // estimates below for the # bits required seems like a good guesstimate. + + // VARIABLE - # bits (range) - VARIABLES AFFECTED + // tree type - 5 bits (32) - + // branches - 6 bits (64) - numBranches + // splits - 6 bits (64) - segsplits + // leafiness - 3 bits (8) - numLeaves + // branch spread - 5 bits (32) - splitAngle(V), rotate(V) + // angle - 5 bits (32) - downAngle(V) + // branch length - 6 bits (64) - branchlength(V) + // randomness - 7 bits (128) - percentage for randomness of the (V)'s + // basesize - 5 bits (32) - basesize + + // total - 48 bits + + //U8 mNetSpecies; + +}; + +#endif diff --git a/indra/llprimitive/llvolumemessage.cpp b/indra/llprimitive/llvolumemessage.cpp new file mode 100644 index 0000000000..d2f1e12526 --- /dev/null +++ b/indra/llprimitive/llvolumemessage.cpp @@ -0,0 +1,534 @@ +/** + * @file llvolumemessage.cpp + * @brief LLVolumeMessage base class + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "linden_common.h" + +#include "message.h" +#include "llvolumemessage.h" +#include "lldatapacker.h" + +//============================================================================ + +// LLVolumeMessage is just a wrapper class; all members are static + +//============================================================================ + +bool LLVolumeMessage::packProfileParams( + const LLProfileParams* params, + LLMessageSystem *mesgsys) +{ + // Default to cylinder + static LLProfileParams defaultparams(LL_PCODE_PROFILE_CIRCLE, U8(0), U8(0), U8(0)); + + if (!params) + params = &defaultparams; + + U8 tempU8; + tempU8 = params->getCurveType(); + mesgsys->addU8Fast(_PREHASH_ProfileCurve, tempU8); + + tempU8 = (U8) llround( params->getBegin() / CUT_QUANTA); + mesgsys->addU8Fast(_PREHASH_ProfileBegin, tempU8); + + tempU8 = 200 - (U8) llround(params->getEnd() / CUT_QUANTA); + mesgsys->addU8Fast(_PREHASH_ProfileEnd, tempU8); + + tempU8 = (S8) llround(params->getHollow() / SHEAR_QUANTA); + mesgsys->addU8Fast(_PREHASH_ProfileHollow, tempU8); + + return true; +} + +bool LLVolumeMessage::packProfileParams( + const LLProfileParams* params, + LLDataPacker &dp) +{ + // Default to cylinder + static LLProfileParams defaultparams(LL_PCODE_PROFILE_CIRCLE, U8(0), U8(0), U8(0)); + + if (!params) + params = &defaultparams; + + U8 tempU8; + tempU8 = params->getCurveType(); + dp.packU8(tempU8, "Curve"); + + tempU8 = (U8) llround( params->getBegin() / CUT_QUANTA); + dp.packU8(tempU8, "Begin"); + + tempU8 = 200 - (U8) llround(params->getEnd() / CUT_QUANTA); + dp.packU8(tempU8, "End"); + + tempU8 = (S8) llround(params->getHollow() / SHEAR_QUANTA); + dp.packU8(tempU8, "Hollow"); + return true; +} + +bool LLVolumeMessage::unpackProfileParams( + LLProfileParams* params, + LLMessageSystem* mesgsys, + char* block_name, + S32 block_num) +{ + bool ok = true; + U8 temp_u8; + F32 temp_f32; + + mesgsys->getU8Fast(block_name, _PREHASH_ProfileCurve, temp_u8, block_num); + params->setCurveType(temp_u8); + + mesgsys->getU8Fast(block_name, _PREHASH_ProfileBegin, temp_u8, block_num); + temp_f32 = temp_u8 * CUT_QUANTA; + if (temp_f32 > 1.f) + { + llwarns << "Profile begin out of range: " << temp_f32 + << ". Clamping to 0.0." << llendl; + temp_f32 = 0.f; + ok = false; + } + params->setBegin(temp_f32); + + mesgsys->getU8Fast(block_name, _PREHASH_ProfileEnd, temp_u8, block_num); + temp_f32 = temp_u8 * CUT_QUANTA; + if (temp_f32 > 1.f) + { + llwarns << "Profile end out of range: " << 1.f - temp_f32 + << ". Clamping to 1.0." << llendl; + temp_f32 = 1.f; + ok = false; + } + params->setEnd(1.f - temp_f32); + + mesgsys->getU8Fast(block_name, _PREHASH_ProfileHollow, temp_u8, block_num); + temp_f32 = temp_u8 * SCALE_QUANTA; + if (temp_f32 > 1.f) + { + llwarns << "Profile hollow out of range: " << temp_f32 + << ". Clamping to 0.0." << llendl; + temp_f32 = 0.f; + ok = false; + } + params->setHollow(temp_f32); + + /* + llinfos << "Unpacking Profile Block " << block_num << llendl; + llinfos << "Curve: " << (U32)getCurve() << llendl; + llinfos << "Begin: " << getBegin() << llendl; + llinfos << "End: " << getEnd() << llendl; + llinfos << "Hollow: " << getHollow() << llendl; + */ + return ok; + +} + +bool LLVolumeMessage::unpackProfileParams( + LLProfileParams* params, + LLDataPacker &dp) +{ + bool ok = true; + U8 temp_u8; + F32 temp_f32; + + dp.unpackU8(temp_u8, "Curve"); + params->setCurveType(temp_u8); + + dp.unpackU8(temp_u8, "Begin"); + temp_f32 = temp_u8 * CUT_QUANTA; + if (temp_f32 > 1.f) + { + llwarns << "Profile begin out of range: " << temp_f32 << llendl; + llwarns << "Clamping to 0.0" << llendl; + temp_f32 = 0.f; + ok = false; + } + params->setBegin(temp_f32); + + dp.unpackU8(temp_u8, "End"); + temp_f32 = temp_u8 * CUT_QUANTA; + if (temp_f32 > 1.f) + { + llwarns << "Profile end out of range: " << 1.f - temp_f32 << llendl; + llwarns << "Clamping to 1.0" << llendl; + temp_f32 = 1.f; + ok = false; + } + params->setEnd(1.f - temp_f32); + + dp.unpackU8(temp_u8, "Hollow"); + temp_f32 = temp_u8 * SCALE_QUANTA; + if (temp_f32 > 1.f) + { + llwarns << "Profile hollow out of range: " << temp_f32 << llendl; + llwarns << "Clamping to 0.0" << llendl; + temp_f32 = 0.f; + ok = false; + } + params->setHollow(temp_f32); + + return ok; +} + +//============================================================================ + +// Quantization: +// For cut begin, range is 0 to 1, quanta is 0.005, 0 maps to 0 +// For cut end, range is 0 to 1, quanta is 0.005, 1 maps to 0 +// For scale, range is 0 to 1, quanta is 0.01, 0 maps to 0, 1 maps to 100 +// For shear, range is -0.5 to 0.5, quanta is 0.01, 0 maps to 0 +// For taper, range is -1 to 1, quanta is 0.01, 0 maps to 0 +bool LLVolumeMessage::packPathParams( + const LLPathParams* params, + LLMessageSystem *mesgsys) +{ + // Default to cylinder with no cut, top same size as bottom, no shear, no twist + static LLPathParams defaultparams(LL_PCODE_PATH_LINE, U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), 0); + if (!params) + params = &defaultparams; + + U8 curve = params->getCurveType(); + mesgsys->addU8Fast(_PREHASH_PathCurve, curve); + + U8 begin = (U8) llround(params->getBegin() / SCALE_QUANTA); + mesgsys->addU8Fast(_PREHASH_PathBegin, begin); + + U8 end = 100 - (U8) llround(params->getEnd() / SCALE_QUANTA); + mesgsys->addU8Fast(_PREHASH_PathEnd, end); + + // Avoid truncation problem with direct F32->U8 cast. + // (e.g., (U8) (0.50 / 0.01) = (U8) 49.9999999 = 49 not 50. + + U8 pack_scale_x = 200 - (U8) llround(params->getScaleX() / SCALE_QUANTA); + mesgsys->addU8Fast(_PREHASH_PathScaleX, pack_scale_x ); + + U8 pack_scale_y = 200 - (U8) llround(params->getScaleY() / SCALE_QUANTA); + mesgsys->addU8Fast(_PREHASH_PathScaleY, pack_scale_y ); + + U8 pack_shear_x = (U8) llround(params->getShearX() / SHEAR_QUANTA); + mesgsys->addU8Fast(_PREHASH_PathShearX, pack_shear_x ); + + U8 pack_shear_y = (U8) llround(params->getShearY() / SHEAR_QUANTA); + mesgsys->addU8Fast(_PREHASH_PathShearY, pack_shear_y ); + + S8 twist = (S8) llround(params->getTwist() / SCALE_QUANTA); + mesgsys->addS8Fast(_PREHASH_PathTwist, twist); + + S8 twist_begin = (S8) llround(params->getTwistBegin() / SCALE_QUANTA); + mesgsys->addS8Fast(_PREHASH_PathTwistBegin, twist_begin); + + S8 radius_offset = (S8) llround(params->getRadiusOffset() / SCALE_QUANTA); + mesgsys->addS8Fast(_PREHASH_PathRadiusOffset, radius_offset); + + S8 taper_x = (S8) llround(params->getTaperX() / TAPER_QUANTA); + mesgsys->addS8Fast(_PREHASH_PathTaperX, taper_x); + + S8 taper_y = (S8) llround(params->getTaperY() / TAPER_QUANTA); + mesgsys->addS8Fast(_PREHASH_PathTaperY, taper_y); + + U8 revolutions = (U8) llround( (params->getRevolutions() - 1.0f) / REV_QUANTA); + mesgsys->addU8Fast(_PREHASH_PathRevolutions, revolutions); + + S8 skew = (S8) llround(params->getSkew() / SCALE_QUANTA); + mesgsys->addS8Fast(_PREHASH_PathSkew, skew); + + return true; +} + +bool LLVolumeMessage::packPathParams( + const LLPathParams* params, + LLDataPacker &dp) +{ + // Default to cylinder with no cut, top same size as bottom, no shear, no twist + static LLPathParams defaultparams(LL_PCODE_PATH_LINE, U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), 0); + if (!params) + params = &defaultparams; + + U8 curve = params->getCurveType(); + dp.packU8(curve, "Curve"); + + U8 begin = (U8) llround(params->getBegin() / SCALE_QUANTA); + dp.packU8(begin, "Begin"); + + U8 end = 100 - (U8) llround(params->getEnd() / SCALE_QUANTA); + dp.packU8(end, "End"); + + // Avoid truncation problem with direct F32->U8 cast. + // (e.g., (U8) (0.50 / 0.01) = (U8) 49.9999999 = 49 not 50. + + U8 pack_scale_x = 200 - (U8) llround(params->getScaleX() / SCALE_QUANTA); + dp.packU8(pack_scale_x, "ScaleX"); + + U8 pack_scale_y = 200 - (U8) llround(params->getScaleY() / SCALE_QUANTA); + dp.packU8(pack_scale_y, "ScaleY"); + + S8 pack_shear_x = (S8) llround(params->getShearX() / SHEAR_QUANTA); + dp.packU8(*(U8 *)&pack_shear_x, "ShearX"); + + S8 pack_shear_y = (S8) llround(params->getShearY() / SHEAR_QUANTA); + dp.packU8(*(U8 *)&pack_shear_y, "ShearY"); + + S8 twist = (S8) llround(params->getTwist() / SCALE_QUANTA); + dp.packU8(*(U8 *)&twist, "Twist"); + + S8 twist_begin = (S8) llround(params->getTwistBegin() / SCALE_QUANTA); + dp.packU8(*(U8 *)&twist_begin, "TwistBegin"); + + S8 radius_offset = (S8) llround(params->getRadiusOffset() / SCALE_QUANTA); + dp.packU8(*(U8 *)&radius_offset, "RadiusOffset"); + + S8 taper_x = (S8) llround(params->getTaperX() / TAPER_QUANTA); + dp.packU8(*(U8 *)&taper_x, "TaperX"); + + S8 taper_y = (S8) llround(params->getTaperY() / TAPER_QUANTA); + dp.packU8(*(U8 *)&taper_y, "TaperY"); + + U8 revolutions = (U8) llround( (params->getRevolutions() - 1.0f) / REV_QUANTA); + dp.packU8(*(U8 *)&revolutions, "Revolutions"); + + S8 skew = (S8) llround(params->getSkew() / SCALE_QUANTA); + dp.packU8(*(U8 *)&skew, "Skew"); + + return true; +} + +bool LLVolumeMessage::unpackPathParams( + LLPathParams* params, + LLMessageSystem* mesgsys, + char* block_name, + S32 block_num) +{ + U8 curve; + mesgsys->getU8Fast(block_name, _PREHASH_PathCurve, curve, block_num); + params->setCurveType(curve); + + U8 begin; + mesgsys->getU8Fast(block_name, _PREHASH_PathBegin, begin, block_num); + params->setBegin((F32)(begin * SCALE_QUANTA)); + + U8 end; + mesgsys->getU8Fast(block_name, _PREHASH_PathEnd, end, block_num); + params->setEnd((F32)((100 - end) * SCALE_QUANTA)); + + U8 pack_scale_x, pack_scale_y; + mesgsys->getU8Fast(block_name, _PREHASH_PathScaleX, pack_scale_x, block_num); + mesgsys->getU8Fast(block_name, _PREHASH_PathScaleY, pack_scale_y, block_num); + F32 x = (F32) (200 - pack_scale_x) * SCALE_QUANTA; + F32 y = (F32) (200 - pack_scale_y) * SCALE_QUANTA; + params->setScale( x, y ); + + S8 shear_x_quant, shear_y_quant; + mesgsys->getS8Fast(block_name, _PREHASH_PathShearX, shear_x_quant, block_num); + mesgsys->getS8Fast(block_name, _PREHASH_PathShearY, shear_y_quant, block_num); + F32 shear_x = (F32) shear_x_quant * SHEAR_QUANTA; + F32 shear_y = (F32) shear_y_quant * SHEAR_QUANTA; + params->setShear( shear_x, shear_y ); + + S8 twist; + mesgsys->getS8Fast(block_name, _PREHASH_PathTwist, twist, block_num ); + params->setTwist((F32)(twist * SCALE_QUANTA)); + + S8 twist_begin; + mesgsys->getS8Fast(block_name, _PREHASH_PathTwistBegin, twist_begin, block_num ); + params->setTwistBegin((F32)(twist_begin * SCALE_QUANTA)); + + S8 radius_offset; + mesgsys->getS8Fast(block_name, _PREHASH_PathRadiusOffset, radius_offset, block_num ); + params->setRadiusOffset((F32)(radius_offset * SCALE_QUANTA)); + + S8 taper_x_quant, taper_y_quant; + mesgsys->getS8Fast(block_name, _PREHASH_PathTaperX, taper_x_quant, block_num ); + mesgsys->getS8Fast(block_name, _PREHASH_PathTaperY, taper_y_quant, block_num ); + F32 taper_x = (F32)(taper_x_quant * TAPER_QUANTA); + F32 taper_y = (F32)(taper_y_quant * TAPER_QUANTA); + params->setTaper( taper_x, taper_y ); + + U8 revolutions; + mesgsys->getU8Fast(block_name, _PREHASH_PathRevolutions, revolutions, block_num ); + params->setRevolutions((F32)(revolutions * REV_QUANTA + 1.0f)); + + S8 skew; + mesgsys->getS8Fast(block_name, _PREHASH_PathSkew, skew, block_num ); + params->setSkew((F32)(skew * SCALE_QUANTA)); + +/* + llinfos << "Unpacking Path Block " << block_num << llendl; + llinfos << "Curve: " << (U32)params->getCurve() << llendl; + llinfos << "Begin: " << params->getBegin() << llendl; + llinfos << "End: " << params->getEnd() << llendl; + llinfos << "Scale: " << params->getScale() << llendl; + llinfos << "Twist: " << params->getTwist() << llendl; +*/ + + return true; + +} + +bool LLVolumeMessage::unpackPathParams(LLPathParams* params, LLDataPacker &dp) +{ + U8 value; + S8 svalue; + dp.unpackU8(value, "Curve"); + params->setCurveType( value ); + + dp.unpackU8(value, "Begin"); + params->setBegin((F32)(value * SCALE_QUANTA)); + + dp.unpackU8(value, "End"); + params->setEnd((F32)((100 - value) * SCALE_QUANTA)); + + dp.unpackU8(value, "ScaleX"); + F32 x = (F32) (200 - value) * SCALE_QUANTA; + dp.unpackU8(value, "ScaleY"); + F32 y = (F32) (200 - value) * SCALE_QUANTA; + params->setScale( x, y ); + + dp.unpackU8(value, "ShearX"); + svalue = *(S8 *)&value; + F32 shear_x = (F32) svalue * SHEAR_QUANTA; + dp.unpackU8(value, "ShearY"); + svalue = *(S8 *)&value; + F32 shear_y = (F32) svalue * SHEAR_QUANTA; + params->setShear( shear_x, shear_y ); + + dp.unpackU8(value, "Twist"); + svalue = *(S8 *)&value; + params->setTwist((F32)(svalue * SCALE_QUANTA)); + + dp.unpackU8(value, "TwistBegin"); + svalue = *(S8 *)&value; + params->setTwistBegin((F32)(svalue * SCALE_QUANTA)); + + dp.unpackU8(value, "RadiusOffset"); + svalue = *(S8 *)&value; + params->setRadiusOffset((F32)(svalue * SCALE_QUANTA)); + + dp.unpackU8(value, "TaperX"); + svalue = *(S8 *)&value; + params->setTaperX((F32)(svalue * TAPER_QUANTA)); + + dp.unpackU8(value, "TaperY"); + svalue = *(S8 *)&value; + params->setTaperY((F32)(svalue * TAPER_QUANTA)); + + dp.unpackU8(value, "Revolutions"); + params->setRevolutions((F32)(value * REV_QUANTA + 1.0f)); + + dp.unpackU8(value, "Skew"); + svalue = *(S8 *)&value; + params->setSkew((F32)(svalue * SCALE_QUANTA)); + + return true; +} + +//============================================================================ + +// static +bool LLVolumeMessage::constrainVolumeParams(LLVolumeParams& params) +{ + bool ok = true; + + // This is called immediately after an unpack. feed the raw data + // through the checked setters to constraint it to a valid set of + // volume params. + ok &= params.setType( + params.getProfileParams().getCurveType(), + params.getPathParams().getCurveType()); + ok &= params.setBeginAndEndS( + params.getProfileParams().getBegin(), + params.getProfileParams().getEnd()); + ok &= params.setBeginAndEndT( + params.getPathParams().getBegin(), + params.getPathParams().getEnd()); + ok &= params.setHollow(params.getProfileParams().getHollow()); + ok &= params.setTwistBegin(params.getPathParams().getTwistBegin()); + ok &= params.setTwistEnd(params.getPathParams().getTwistEnd()); + ok &= params.setRatio( + params.getPathParams().getScaleX(), + params.getPathParams().getScaleY()); + ok &= params.setShear( + params.getPathParams().getShearX(), + params.getPathParams().getShearY()); + ok &= params.setTaper( + params.getPathParams().getTaperX(), + params.getPathParams().getTaperY()); + ok &= params.setRevolutions(params.getPathParams().getRevolutions()); + ok &= params.setRadiusOffset(params.getPathParams().getRadiusOffset()); + ok &= params.setSkew(params.getPathParams().getSkew()); + if(!ok) + { + llwarns << "LLVolumeMessage::constrainVolumeParams() - " + << "forced to constrain incoming volume params." << llendl; + } + return ok; +} + +bool LLVolumeMessage::packVolumeParams(const LLVolumeParams* params, LLMessageSystem *mesgsys) +{ + // llinfos << "pack volume" << llendl; + if (params) + { + packPathParams(¶ms->getPathParams(), mesgsys); + packProfileParams(¶ms->getProfileParams(), mesgsys); + } + else + { + packPathParams(0, mesgsys); + packProfileParams(0, mesgsys); + } + return true; +} + +bool LLVolumeMessage::packVolumeParams(const LLVolumeParams* params, LLDataPacker &dp) +{ + // llinfos << "pack volume" << llendl; + if (params) + { + packPathParams(¶ms->getPathParams(), dp); + packProfileParams(¶ms->getProfileParams(), dp); + } + else + { + packPathParams(0, dp); + packProfileParams(0, dp); + } + return true; +} + +bool LLVolumeMessage::unpackVolumeParams( + LLVolumeParams* params, + LLMessageSystem* mesgsys, + char* block_name, + S32 block_num) +{ + bool ok = true; + ok &= unpackPathParams( + ¶ms->getPathParams(), + mesgsys, + block_name, + block_num); + ok &= unpackProfileParams( + ¶ms->getProfileParams(), + mesgsys, + block_name, + block_num); + ok &= constrainVolumeParams(*params); + + return ok; +} + +bool LLVolumeMessage::unpackVolumeParams( + LLVolumeParams* params, + LLDataPacker &dp) +{ + bool ok = true; + ok &= unpackPathParams(¶ms->getPathParams(), dp); + ok &= unpackProfileParams(¶ms->getProfileParams(), dp); + ok &= constrainVolumeParams(*params); + return ok; +} + +//============================================================================ diff --git a/indra/llprimitive/llvolumemessage.h b/indra/llprimitive/llvolumemessage.h new file mode 100644 index 0000000000..299d5813a0 --- /dev/null +++ b/indra/llprimitive/llvolumemessage.h @@ -0,0 +1,74 @@ +/** + * @file llvolumemessage.h + * @brief LLVolumeMessage base class + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_LLVOLUMEMESSAGE_H +#define LL_LLVOLUMEMESSAGE_H + +#include "llvolume.h" + +class LLMessageSystem; +class LLDataPacker; + +// wrapper class for some volume/message functions +class LLVolumeMessage +{ +protected: + // The profile and path params are protected since they do not do + // any kind of parameter validation or clamping. Use the public + // pack and unpack volume param methods below + + static bool packProfileParams( + const LLProfileParams* params, + LLMessageSystem* mesgsys); + static bool packProfileParams( + const LLProfileParams* params, + LLDataPacker& dp); + static bool unpackProfileParams( + LLProfileParams* params, + LLMessageSystem* mesgsys, + char* block_name, + S32 block_num = 0); + static bool unpackProfileParams(LLProfileParams* params, LLDataPacker& dp); + + static bool packPathParams( + const LLPathParams* params, + LLMessageSystem* mesgsys); + static bool packPathParams(const LLPathParams* params, LLDataPacker& dp); + static bool unpackPathParams( + LLPathParams* params, + LLMessageSystem* mesgsys, + char* block_name, + S32 block_num = 0); + static bool unpackPathParams(LLPathParams* params, LLDataPacker& dp); + +public: + /** + * @brief This method constrains any volume params to make them valid. + * + * @param[in,out] Possibly invalid params in, always valid out. + * @return Returns true if the in params were valid, and therefore + * unchanged. + */ + static bool constrainVolumeParams(LLVolumeParams& params); + + static bool packVolumeParams( + const LLVolumeParams* params, + LLMessageSystem* mesgsys); + static bool packVolumeParams( + const LLVolumeParams* params, + LLDataPacker& dp); + static bool unpackVolumeParams( + LLVolumeParams* params, + LLMessageSystem* mesgsys, + char* block_name, + S32 block_num = 0); + static bool unpackVolumeParams(LLVolumeParams* params, LLDataPacker &dp); +}; + +#endif // LL_LLVOLUMEMESSAGE_H + diff --git a/indra/llprimitive/llvolumexml.cpp b/indra/llprimitive/llvolumexml.cpp new file mode 100644 index 0000000000..3c9d4d3b39 --- /dev/null +++ b/indra/llprimitive/llvolumexml.cpp @@ -0,0 +1,57 @@ +/** + * @file llvolumexml.cpp + * @brief LLVolumeXml base class + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "linden_common.h" + +#include "llvolumexml.h" + +//============================================================================ + +// LLVolumeXml is just a wrapper class; all members are static + +//============================================================================ + +LLXMLNode *LLVolumeXml::exportProfileParams(const LLProfileParams* params) +{ + LLXMLNode *ret = new LLXMLNode("profile", FALSE); + + ret->createChild("curve_type", TRUE)->setByteValue(1, ¶ms->getCurveType()); + ret->createChild("interval", FALSE)->setFloatValue(2, ¶ms->getBegin()); + ret->createChild("hollow", FALSE)->setFloatValue(1, ¶ms->getHollow()); + + return ret; +} + + +LLXMLNode *LLVolumeXml::exportPathParams(const LLPathParams* params) +{ + LLXMLNode *ret = new LLXMLNode("path", FALSE); + ret->createChild("curve_type", TRUE)->setByteValue(1, ¶ms->getCurveType()); + ret->createChild("interval", FALSE)->setFloatValue(2, ¶ms->getBegin()); + ret->createChild("scale", FALSE)->setFloatValue(2, params->getScale().mV); + ret->createChild("shear", FALSE)->setFloatValue(2, params->getShear().mV); + ret->createChild("twist_interval", FALSE)->setFloatValue(2, ¶ms->getTwistBegin()); + ret->createChild("radius_offset", FALSE)->setFloatValue(1, ¶ms->getRadiusOffset()); + ret->createChild("taper", FALSE)->setFloatValue(2, params->getTaper().mV); + ret->createChild("revolutions", FALSE)->setFloatValue(1, ¶ms->getRevolutions()); + ret->createChild("skew", FALSE)->setFloatValue(1, ¶ms->getSkew()); + + return ret; +} + + +LLXMLNode *LLVolumeXml::exportVolumeParams(const LLVolumeParams* params) +{ + LLXMLNode *ret = new LLXMLNode("shape", FALSE); + + exportPathParams(¶ms->getPathParams())->setParent(ret); + exportProfileParams(¶ms->getProfileParams())->setParent(ret); + + return ret; +} + diff --git a/indra/llprimitive/llvolumexml.h b/indra/llprimitive/llvolumexml.h new file mode 100644 index 0000000000..5d105f148a --- /dev/null +++ b/indra/llprimitive/llvolumexml.h @@ -0,0 +1,27 @@ +/** + * @file llvolumexml.h + * @brief LLVolumeXml base class + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_LLVOLUMEXML_H +#define LL_LLVOLUMEXML_H + +#include "llvolume.h" +#include "llxmlnode.h" + +// wrapper class for some volume/message functions +class LLVolumeXml +{ +public: + static LLXMLNode* exportProfileParams(const LLProfileParams* params); + + static LLXMLNode* exportPathParams(const LLPathParams* params); + + static LLXMLNode* exportVolumeParams(const LLVolumeParams* params); +}; + +#endif // LL_LLVOLUMEXML_H + diff --git a/indra/llprimitive/material_codes.h b/indra/llprimitive/material_codes.h new file mode 100644 index 0000000000..f9c05017c2 --- /dev/null +++ b/indra/llprimitive/material_codes.h @@ -0,0 +1,35 @@ +/** + * @file material_codes.h + * @brief Material_codes definitions + * + * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_MATERIAL_CODES_H +#define LL_MATERIAL_CODES_H + +#include "lluuid.h" + + // material types +const U8 LL_MCODE_STONE = 0; +const U8 LL_MCODE_METAL = 1; +const U8 LL_MCODE_GLASS = 2; +const U8 LL_MCODE_WOOD = 3; +const U8 LL_MCODE_FLESH = 4; +const U8 LL_MCODE_PLASTIC = 5; +const U8 LL_MCODE_RUBBER = 6; +const U8 LL_MCODE_LIGHT = 7; +const U8 LL_MCODE_END = 8; +const U8 LL_MCODE_MASK = 0x0F; + +const LLUUID LL_DEFAULT_STONE_UUID("87c5765b-aa26-43eb-b8c6-c09a1ca6208e"); +const LLUUID LL_DEFAULT_METAL_UUID("6f3c53e9-ba60-4010-8f3e-30f51a762476"); +const LLUUID LL_DEFAULT_GLASS_UUID("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); +const LLUUID LL_DEFAULT_WOOD_UUID("89556747-24cb-43ed-920b-47caed15465f"); +const LLUUID LL_DEFAULT_FLESH_UUID("80736669-e4b9-450e-8890-d5169f988a50"); +const LLUUID LL_DEFAULT_PLASTIC_UUID("304fcb4e-7d33-4339-ba80-76d3d22dc11a"); +const LLUUID LL_DEFAULT_RUBBER_UUID("9fae0bc5-666d-477e-9f70-84e8556ec867"); +const LLUUID LL_DEFAULT_LIGHT_UUID("00000000-0000-0000-0000-000000000000"); + +#endif |