From c47d42d9459445d9e9869c49ebe66a0671a3a0a7 Mon Sep 17 00:00:00 2001 From: Kadah_Coba Date: Wed, 29 Jun 2011 23:40:20 -0700 Subject: STORM-1315 Ability to do simple math in numeric edit fields --- indra/llmath/CMakeLists.txt | 4 + indra/llmath/llcalc.cpp | 150 +++++++++++++++++++++++++++++++++++++ indra/llmath/llcalc.h | 83 +++++++++++++++++++++ indra/llmath/llcalcparser.cpp | 46 ++++++++++++ indra/llmath/llcalcparser.h | 169 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 452 insertions(+) create mode 100644 indra/llmath/llcalc.cpp create mode 100644 indra/llmath/llcalc.h create mode 100644 indra/llmath/llcalcparser.cpp create mode 100644 indra/llmath/llcalcparser.h (limited to 'indra/llmath') diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index 9dadad7dd3..cd100cdf9f 100644 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -12,6 +12,8 @@ include_directories( set(llmath_SOURCE_FILES llbbox.cpp llbboxlocal.cpp + llcalc.cpp + llcalcparser.cpp llcamera.cpp llcoordframe.cpp llline.cpp @@ -46,6 +48,8 @@ set(llmath_HEADER_FILES coordframe.h llbbox.h llbboxlocal.h + llcalc.h + llcalcparser.h llcamera.h llcoord.h llcoordframe.h diff --git a/indra/llmath/llcalc.cpp b/indra/llmath/llcalc.cpp new file mode 100644 index 0000000000..f399463a47 --- /dev/null +++ b/indra/llmath/llcalc.cpp @@ -0,0 +1,150 @@ +/* + * LLCalc.cpp + * SecondLife + * + * Created by Aimee Walton on 28/09/2008. + * Copyright 2008 Aimee Walton. + * + */ + +#include "linden_common.h" + +#include "llcalc.h" + +#include "llcalcparser.h" +#include "llmath.h" + + +// Variable names for use in the build floater +const char* LLCalc::X_POS = "PX"; +const char* LLCalc::Y_POS = "PY"; +const char* LLCalc::Z_POS = "PZ"; +const char* LLCalc::X_SCALE = "SX"; +const char* LLCalc::Y_SCALE = "SY"; +const char* LLCalc::Z_SCALE = "SZ"; +const char* LLCalc::X_ROT = "RX"; +const char* LLCalc::Y_ROT = "RY"; +const char* LLCalc::Z_ROT = "RZ"; +const char* LLCalc::HOLLOW = "HLW"; +const char* LLCalc::CUT_BEGIN = "CB"; +const char* LLCalc::CUT_END = "CE"; +const char* LLCalc::PATH_BEGIN = "PB"; +const char* LLCalc::PATH_END = "PE"; +const char* LLCalc::TWIST_BEGIN = "TB"; +const char* LLCalc::TWIST_END = "TE"; +const char* LLCalc::X_SHEAR = "SHX"; +const char* LLCalc::Y_SHEAR = "SHY"; +const char* LLCalc::X_TAPER = "TPX"; +const char* LLCalc::Y_TAPER = "TPY"; +const char* LLCalc::RADIUS_OFFSET = "ROF"; +const char* LLCalc::REVOLUTIONS = "REV"; +const char* LLCalc::SKEW = "SKW"; +const char* LLCalc::X_HOLE = "HLX"; +const char* LLCalc::Y_HOLE = "HLY"; +const char* LLCalc::TEX_U_SCALE = "TSU"; +const char* LLCalc::TEX_V_SCALE = "TSV"; +const char* LLCalc::TEX_U_OFFSET = "TOU"; +const char* LLCalc::TEX_V_OFFSET = "TOV"; +const char* LLCalc::TEX_ROTATION = "TROT"; +const char* LLCalc::TEX_TRANSPARENCY = "TRNS"; +const char* LLCalc::TEX_GLOW = "GLOW"; + + +LLCalc* LLCalc::sInstance = NULL; + +LLCalc::LLCalc() : mLastErrorPos(0) +{ +// mUserVariables = new calc_map_t; + mVariables = new calc_map_t; + mConstants = new calc_map_t; + + // Init table of constants + (*mConstants)["PI"] = F_PI; + (*mConstants)["TWO_PI"] = F_TWO_PI; + (*mConstants)["PI_BY_TWO"] = F_PI_BY_TWO; + (*mConstants)["SQRT2"] = F_SQRT2; + (*mConstants)["DEG_TO_RAD"] = DEG_TO_RAD; + (*mConstants)["RAD_TO_DEG"] = RAD_TO_DEG; + (*mConstants)["GRAVITY"] = GRAVITY; +} + +LLCalc::~LLCalc() +{ + delete mConstants; + delete mVariables; +// delete mUserVariables; +} + +//static +void LLCalc::cleanUp() +{ + delete sInstance; + sInstance = NULL; +} + +//static +LLCalc* LLCalc::getInstance() +{ + if (!sInstance) sInstance = new LLCalc(); + return sInstance; +} + +void LLCalc::setVar(const std::string& name, const F32& value) +{ + (*mVariables)[name] = value; +} + +void LLCalc::clearVar(const std::string& name) +{ + mVariables->erase(name); +} + +void LLCalc::clearAllVariables() +{ + mVariables->clear(); +} + +/* +void LLCalc::updateVariables(LLSD& vars) +{ + LLSD::map_iterator cIt = vars.beginMap(); + for(; cIt != vars.endMap(); cIt++) + { + setVar(cIt->first, (F32)(LLSD::Real)cIt->second); + } +} +*/ + +bool LLCalc::evalString(const std::string& expression, F32& result) +{ + std::string expr_upper = expression; + LLStringUtil::toUpper(expr_upper); + + LLCalcParser calc(result, mConstants, mVariables); + + mLastErrorPos = 0; + std::string::iterator start = expr_upper.begin(); + parse_info info; + + try + { + info = parse(start, expr_upper.end(), calc, space_p); + lldebugs << "Math expression: " << expression << " = " << result << llendl; + } + catch(parser_error &e) + { + mLastErrorPos = e.where - expr_upper.begin(); + + llinfos << "Calc parser exception: " << e.descriptor << " at " << mLastErrorPos << " in expression: " << expression << llendl; + return false; + } + + if (!info.full) + { + mLastErrorPos = info.stop - expr_upper.begin(); + llinfos << "Unhandled syntax error at " << mLastErrorPos << " in expression: " << expression << llendl; + return false; + } + + return true; +} diff --git a/indra/llmath/llcalc.h b/indra/llmath/llcalc.h new file mode 100644 index 0000000000..23c83f623e --- /dev/null +++ b/indra/llmath/llcalc.h @@ -0,0 +1,83 @@ +/* + * LLCalc.h + * SecondLife + * + * Created by Aimee Walton on 28/09/2008. + * Copyright 2008 Aimee Walton. + * + */ + +#ifndef LL_CALC_H +#define LL_CALC_H + +#include +#include + +class LLCalc +{ +public: + LLCalc(); + ~LLCalc(); + + // Variable name constants + static const char* X_POS; + static const char* Y_POS; + static const char* Z_POS; + static const char* X_SCALE; + static const char* Y_SCALE; + static const char* Z_SCALE; + static const char* X_ROT; + static const char* Y_ROT; + static const char* Z_ROT; + static const char* HOLLOW; + static const char* CUT_BEGIN; + static const char* CUT_END; + static const char* PATH_BEGIN; + static const char* PATH_END; + static const char* TWIST_BEGIN; + static const char* TWIST_END; + static const char* X_SHEAR; + static const char* Y_SHEAR; + static const char* X_TAPER; + static const char* Y_TAPER; + static const char* RADIUS_OFFSET; + static const char* REVOLUTIONS; + static const char* SKEW; + static const char* X_HOLE; + static const char* Y_HOLE; + static const char* TEX_U_SCALE; + static const char* TEX_V_SCALE; + static const char* TEX_U_OFFSET; + static const char* TEX_V_OFFSET; + static const char* TEX_ROTATION; + static const char* TEX_TRANSPARENCY; + static const char* TEX_GLOW; + + void setVar(const std::string& name, const F32& value); + void clearVar(const std::string& name); + void clearAllVariables(); +// void updateVariables(LLSD& vars); + + bool evalString(const std::string& expression, F32& result); + std::string::size_type getLastErrorPos() { return mLastErrorPos; } + + static LLCalc* getInstance(); + static void cleanUp(); + + typedef std::map calc_map_t; + +private: + std::string::size_type mLastErrorPos; + + calc_map_t* mConstants; + calc_map_t* mVariables; + + // *TODO: Add support for storing user defined variables, and stored functions. + // Will need UI work, and a means to save them between sessions. +// calc_map_t* mUserVariables; + + // "There shall be only one" + static LLCalc* sInstance; +}; + +#endif // LL_CALC_H diff --git a/indra/llmath/llcalcparser.cpp b/indra/llmath/llcalcparser.cpp new file mode 100644 index 0000000000..fd55376fa9 --- /dev/null +++ b/indra/llmath/llcalcparser.cpp @@ -0,0 +1,46 @@ +/* + * LLCalcParser.cpp + * SecondLife + * + * Created by Aimee Walton on 28/09/2008. + * Copyright 2008 Aimee Walton. + * + */ + +#include "linden_common.h" + +#include "llcalcparser.h" +using namespace boost::spirit::classic; + +F32 LLCalcParser::lookup(const std::string::iterator& start, const std::string::iterator& end) const +{ + LLCalc::calc_map_t::iterator iter; + + std::string name(start, end); + + if (mConstants) + { + iter = mConstants->find(name); + if (iter != mConstants->end()) + { + return (*iter).second; + } + } + else + { + // This should never happen! + throw_(end, std::string("Missing constants table")); + } + + if (mVariables) + { + iter = mVariables->find(name); + if (iter != mVariables->end()) + { + return (*iter).second; + } + } + + throw_(end, std::string("Unknown symbol " + name)); + return 0.f; +} diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h new file mode 100644 index 0000000000..a759a35710 --- /dev/null +++ b/indra/llmath/llcalcparser.h @@ -0,0 +1,169 @@ +/* + * LLCalcParser.h + * SecondLife + * + * Created by Aimee Walton on 28/09/2008. + * Copyright 2008 Aimee Walton. + * + */ + +#ifndef LL_CALCPARSER_H +#define LL_CALCPARSER_H + +#include +#include +#include +#include +#include +#include +using namespace boost::spirit::classic; + +#include "llcalc.h" +#include "llmath.h" + +struct LLCalcParser : grammar +{ + LLCalcParser(F32& result, LLCalc::calc_map_t* constants, LLCalc::calc_map_t* vars) : + mResult(result), mConstants(constants), mVariables(vars) {}; + + struct value_closure : closure + { + member1 value; + }; + + template + struct definition + { + // Rule declarations + rule statement, identifier; + rule expression, term, + power, + unary_expr, + factor, + unary_func, + binary_func, + group; + + // start() should return the starting symbol + rule const& start() const { return statement; } + + definition(LLCalcParser const& self) + { + using namespace phoenix; + + assertion assert_domain("Domain error"); +// assertion assert_symbol("Unknown symbol"); + assertion assert_syntax("Syntax error"); + + identifier = + lexeme_d[(alpha_p | '_') >> *(alnum_p | '_')] + ; + + group = + '(' >> expression[group.value = arg1] >> assert_syntax(ch_p(')')) + ; + + unary_func = + ((str_p("SIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sin)(self,arg1)]) | + (str_p("COS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_cos)(self,arg1)]) | + (str_p("TAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_tan)(self,arg1)]) | + (str_p("ASIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_asin)(self,arg1)]) | + (str_p("ACOS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_acos)(self,arg1)]) | + (str_p("ATAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_atan)(self,arg1)]) | + (str_p("SQRT") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sqrt)(self,arg1)]) | + (str_p("LOG") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_log)(self,arg1)]) | + (str_p("EXP") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_exp)(self,arg1)]) | + (str_p("ABS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_fabs)(self,arg1)]) + ) >> assert_syntax(ch_p(')')) + ; + + binary_func = + ((str_p("ATAN2") >> '(' >> expression[binary_func.value = arg1] >> ',' >> + expression[binary_func.value = bind(&LLCalcParser::_atan2)(self, binary_func.value, arg1)]) | + (str_p("MIN") >> '(' >> expression[binary_func.value = arg1] >> ',' >> + expression[binary_func.value = bind(&LLCalcParser::_min)(self, binary_func.value, arg1)]) | + (str_p("MAX") >> '(' >> expression[binary_func.value = arg1] >> ',' >> + expression[binary_func.value = bind(&LLCalcParser::_max)(self, binary_func.value, arg1)]) + ) >> assert_syntax(ch_p(')')) + ; + + // *TODO: Localisation of the decimal point? + // Problem, LLLineEditor::postvalidateFloat accepts a comma when appropriate + // for the current locale. However to do that here could clash with using + // the comma as a separator when passing arguments to functions. + factor = + (ureal_p[factor.value = arg1] | + group[factor.value = arg1] | + unary_func[factor.value = arg1] | + binary_func[factor.value = arg1] | + // Lookup throws an Unknown Symbol error if it is unknown, while this works fine, + // would be "neater" to handle symbol lookup from here with an assertive parser. +// constants_p[factor.value = arg1]| + identifier[factor.value = bind(&LLCalcParser::lookup)(self, arg1, arg2)] + ) >> + // Detect and throw math errors. + assert_domain(eps_p(bind(&LLCalcParser::checkNaN)(self, factor.value))) + ; + + unary_expr = + !ch_p('+') >> factor[unary_expr.value = arg1] | + '-' >> factor[unary_expr.value = -arg1] + ; + + power = + unary_expr[power.value = arg1] >> + *('^' >> assert_syntax(unary_expr[power.value = bind(&powf)(power.value, arg1)])) + ; + + term = + power[term.value = arg1] >> + *(('*' >> assert_syntax(power[term.value *= arg1])) | + ('/' >> assert_syntax(power[term.value /= arg1])) + ) + ; + + expression = + assert_syntax(term[expression.value = arg1]) >> + *(('+' >> assert_syntax(term[expression.value += arg1])) | + ('-' >> assert_syntax(term[expression.value -= arg1])) + ) + ; + + statement = + !ch_p('=') >> ( expression )[var(self.mResult) = arg1] >> (end_p) + ; + } + }; + +private: + // Member functions for semantic actions + F32 lookup(const std::string::iterator&, const std::string::iterator&) const; + F32 _min(const F32& a, const F32& b) const { return llmin(a, b); } + F32 _max(const F32& a, const F32& b) const { return llmax(a, b); } + + bool checkNaN(const F32& a) const { return !llisnan(a); } + + //FIX* non ambigious function fix making SIN() work for calc -Cryogenic Blitz + F32 _sin(const F32& a) const { return sin(DEG_TO_RAD * a); } + F32 _cos(const F32& a) const { return cos(DEG_TO_RAD * a); } + F32 _tan(const F32& a) const { return tan(DEG_TO_RAD * a); } + F32 _asin(const F32& a) const { return asin(a * RAD_TO_DEG); } + F32 _acos(const F32& a) const { return acos(a * RAD_TO_DEG); } + F32 _atan(const F32& a) const { return atan(a * RAD_TO_DEG); } + F32 _sqrt(const F32& a) const { return sqrt(a); } + F32 _log(const F32& a) const { return log(a); } + F32 _exp(const F32& a) const { return exp(a); } + F32 _fabs(const F32& a) const { return fabs(a) * RAD_TO_DEG; } + + F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); } + + + + LLCalc::calc_map_t* mConstants; + LLCalc::calc_map_t* mVariables; +// LLCalc::calc_map_t* mUserVariables; + + F32& mResult; +}; + +#endif // LL_CALCPARSER_H -- cgit v1.2.3 From e08d1e510a2968753cab330c57e9d8ee25102aaf Mon Sep 17 00:00:00 2001 From: Kadah_Coba Date: Thu, 30 Jun 2011 13:48:07 -0700 Subject: Additional functions for STORM-1315 Ability to do simple math in numeric edit fields Support for floor, ceil, modulo. Fixed ABS. Added more constants, SQRT_TWO_PI and SQRT3 --- indra/llmath/llcalc.cpp | 2 ++ indra/llmath/llcalcparser.h | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llcalc.cpp b/indra/llmath/llcalc.cpp index f399463a47..f16dbec63f 100644 --- a/indra/llmath/llcalc.cpp +++ b/indra/llmath/llcalc.cpp @@ -62,7 +62,9 @@ LLCalc::LLCalc() : mLastErrorPos(0) (*mConstants)["PI"] = F_PI; (*mConstants)["TWO_PI"] = F_TWO_PI; (*mConstants)["PI_BY_TWO"] = F_PI_BY_TWO; + (*mConstants)["SQRT_TWO_PI"] = F_SQRT_TWO_PI; (*mConstants)["SQRT2"] = F_SQRT2; + (*mConstants)["SQRT3"] = F_SQRT3; (*mConstants)["DEG_TO_RAD"] = DEG_TO_RAD; (*mConstants)["RAD_TO_DEG"] = RAD_TO_DEG; (*mConstants)["GRAVITY"] = GRAVITY; diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h index a759a35710..600e173661 100644 --- a/indra/llmath/llcalcparser.h +++ b/indra/llmath/llcalcparser.h @@ -73,7 +73,9 @@ struct LLCalcParser : grammar (str_p("SQRT") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sqrt)(self,arg1)]) | (str_p("LOG") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_log)(self,arg1)]) | (str_p("EXP") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_exp)(self,arg1)]) | - (str_p("ABS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_fabs)(self,arg1)]) + (str_p("ABS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_fabs)(self,arg1)]) | + (str_p("FLR") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_floor)(self,arg1)]) | + (str_p("CEIL") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_ceil)(self,arg1)]) ) >> assert_syntax(ch_p(')')) ; @@ -118,7 +120,8 @@ struct LLCalcParser : grammar term = power[term.value = arg1] >> *(('*' >> assert_syntax(power[term.value *= arg1])) | - ('/' >> assert_syntax(power[term.value /= arg1])) + ('/' >> assert_syntax(power[term.value /= arg1])) | + ('%' >> assert_syntax(power[term.value = bind(&fmodf)(term.value, arg1)])) ) ; @@ -153,7 +156,9 @@ private: F32 _sqrt(const F32& a) const { return sqrt(a); } F32 _log(const F32& a) const { return log(a); } F32 _exp(const F32& a) const { return exp(a); } - F32 _fabs(const F32& a) const { return fabs(a) * RAD_TO_DEG; } + F32 _fabs(const F32& a) const { return fabs(a); } + F32 _floor(const F32& a) const { return llfloor(a); } + F32 _ceil(const F32& a) const { return llceil(a); } F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); } -- cgit v1.2.3 From 57c30517817a6458edab6bfdfad7d7112467ca48 Mon Sep 17 00:00:00 2001 From: Kadah_Coba Date: Mon, 4 Jul 2011 14:20:52 -0700 Subject: Changes for STORM-1315 LLCalc Removed dynamic allocation on mVariables and mConstants CS cleanup --- indra/llmath/llcalc.cpp | 33 +++++++++++++-------------------- indra/llmath/llcalc.h | 6 +++--- 2 files changed, 16 insertions(+), 23 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llcalc.cpp b/indra/llmath/llcalc.cpp index f16dbec63f..597d0815fb 100644 --- a/indra/llmath/llcalc.cpp +++ b/indra/llmath/llcalc.cpp @@ -54,27 +54,20 @@ LLCalc* LLCalc::sInstance = NULL; LLCalc::LLCalc() : mLastErrorPos(0) { -// mUserVariables = new calc_map_t; - mVariables = new calc_map_t; - mConstants = new calc_map_t; - // Init table of constants - (*mConstants)["PI"] = F_PI; - (*mConstants)["TWO_PI"] = F_TWO_PI; - (*mConstants)["PI_BY_TWO"] = F_PI_BY_TWO; - (*mConstants)["SQRT_TWO_PI"] = F_SQRT_TWO_PI; - (*mConstants)["SQRT2"] = F_SQRT2; - (*mConstants)["SQRT3"] = F_SQRT3; - (*mConstants)["DEG_TO_RAD"] = DEG_TO_RAD; - (*mConstants)["RAD_TO_DEG"] = RAD_TO_DEG; - (*mConstants)["GRAVITY"] = GRAVITY; + mConstants["PI"] = F_PI; + mConstants["TWO_PI"] = F_TWO_PI; + mConstants["PI_BY_TWO"] = F_PI_BY_TWO; + mConstants["SQRT_TWO_PI"] = F_SQRT_TWO_PI; + mConstants["SQRT2"] = F_SQRT2; + mConstants["SQRT3"] = F_SQRT3; + mConstants["DEG_TO_RAD"] = DEG_TO_RAD; + mConstants["RAD_TO_DEG"] = RAD_TO_DEG; + mConstants["GRAVITY"] = GRAVITY; } LLCalc::~LLCalc() { - delete mConstants; - delete mVariables; -// delete mUserVariables; } //static @@ -93,17 +86,17 @@ LLCalc* LLCalc::getInstance() void LLCalc::setVar(const std::string& name, const F32& value) { - (*mVariables)[name] = value; + mVariables[name] = value; } void LLCalc::clearVar(const std::string& name) { - mVariables->erase(name); + mVariables.erase(name); } void LLCalc::clearAllVariables() { - mVariables->clear(); + mVariables.clear(); } /* @@ -122,7 +115,7 @@ bool LLCalc::evalString(const std::string& expression, F32& result) std::string expr_upper = expression; LLStringUtil::toUpper(expr_upper); - LLCalcParser calc(result, mConstants, mVariables); + LLCalcParser calc(result, &mConstants, &mVariables); mLastErrorPos = 0; std::string::iterator start = expr_upper.begin(); diff --git a/indra/llmath/llcalc.h b/indra/llmath/llcalc.h index 23c83f623e..cc31950cb6 100644 --- a/indra/llmath/llcalc.h +++ b/indra/llmath/llcalc.h @@ -69,12 +69,12 @@ public: private: std::string::size_type mLastErrorPos; - calc_map_t* mConstants; - calc_map_t* mVariables; + calc_map_t mConstants; + calc_map_t mVariables; // *TODO: Add support for storing user defined variables, and stored functions. // Will need UI work, and a means to save them between sessions. -// calc_map_t* mUserVariables; +// calc_map_t mUserVariables; // "There shall be only one" static LLCalc* sInstance; -- cgit v1.2.3 From 7541e6e31b67a40c334c81326c256da712d2a2da Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 8 Jul 2011 14:45:02 -0400 Subject: SH-2014 FIX --- indra/llmath/llvolume.cpp | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 8c81f27784..ea83fac637 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2500,37 +2500,43 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) { U16* n = (U16*) &(norm[0]); - for (U32 j = 0; j < num_verts; ++j) + if(n) { - norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]); - norm_out->div(65535.f); - norm_out->mul(2.f); - norm_out->sub(1.f); - norm_out++; - n += 3; + for (U32 j = 0; j < num_verts; ++j) + { + norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]); + norm_out->div(65535.f); + norm_out->mul(2.f); + norm_out->sub(1.f); + norm_out++; + n += 3; + } } } { U16* t = (U16*) &(tc[0]); - for (U32 j = 0; j < num_verts; j+=2) + if(t) { - if (j < num_verts-1) + for (U32 j = 0; j < num_verts; j+=2) { - tc_out->set((F32) t[0], (F32) t[1], (F32) t[2], (F32) t[3]); - } - else - { - tc_out->set((F32) t[0], (F32) t[1], 0.f, 0.f); - } + if (j < num_verts-1) + { + tc_out->set((F32) t[0], (F32) t[1], (F32) t[2], (F32) t[3]); + } + else + { + tc_out->set((F32) t[0], (F32) t[1], 0.f, 0.f); + } - t += 4; + t += 4; - tc_out->div(65535.f); - tc_out->mul(tc_range); - tc_out->add(min_tc4); + tc_out->div(65535.f); + tc_out->mul(tc_range); + tc_out->add(min_tc4); - tc_out++; + tc_out++; + } } } -- cgit v1.2.3