Merge branch 'master' into game_protocol

This commit is contained in:
hiker 2017-11-05 13:03:15 +11:00
commit 54b32ba6b1
179 changed files with 6045 additions and 3460 deletions

View File

@ -2,7 +2,7 @@
* Reduced RAM and VRAM usage, reducing load times by Auria and Benau * Reduced RAM and VRAM usage, reducing load times by Auria and Benau
* New kart Wilbert by Jymis * New kart Wilbert by Jymis
* New kart Hexley by Jymis * New kart Hexley by Jymis
* New track Cornfield Crossing by samuncle * New tracks Cornfield Crossing and Candela City by samuncle
* Physics improvements and various physics bugfixes by hiker * Physics improvements and various physics bugfixes by hiker
* Kart GFX improvements (exhaust and headlight) * Kart GFX improvements (exhaust and headlight)
* In-game screen recording feature by Benau and Stragus * In-game screen recording feature by Benau and Stragus
@ -10,6 +10,8 @@
* Hardware skinning * Hardware skinning
* New smoother camera by Auria * New smoother camera by Auria
* New grand prix win scene * New grand prix win scene
* Gamepad configuration bugfixes
* 3 Strikes Battles : added spare tire karts
* Various improvements (wall driving fixes, parachutes, GP points, cannon fixes, colorization shader) * Various improvements (wall driving fixes, parachutes, GP points, cannon fixes, colorization shader)
## SuperTuxKart 0.9.2 ## SuperTuxKart 0.9.2

View File

@ -255,11 +255,6 @@ if(UNIX AND NOT APPLE AND NOT SERVER_ONLY)
find_package(X11 REQUIRED) find_package(X11 REQUIRED)
include_directories(${X11_INCLUDE_DIR}) include_directories(${X11_INCLUDE_DIR})
find_package(Xrandr REQUIRED)
if(NOT XRANDR_FOUND)
message(FATAL_ERROR "XRANDR not found.")
endif()
if(USE_LIBBFD) if(USE_LIBBFD)
find_package(Libbfd) find_package(Libbfd)
if(LIBBFD_FOUND) if(LIBBFD_FOUND)
@ -419,7 +414,7 @@ if(NOT SERVER_ONLY)
endif() endif()
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
target_link_libraries(supertuxkart ${X11_LIBRARIES} ${XRANDR_LIBRARIES}) target_link_libraries(supertuxkart ${X11_X11_LIB})
if(USE_LIBBFD) if(USE_LIBBFD)
target_link_libraries(supertuxkart ${LIBBFD_LIBRARIES}) target_link_libraries(supertuxkart ${LIBBFD_LIBRARIES})
endif() endif()

View File

@ -44,7 +44,8 @@ and extract it to stk-code/lib. It contains sources of libraries that are used
in STK, but are not availiable in stk-code repository (curl, freetype, openal). in STK, but are not availiable in stk-code repository (curl, freetype, openal).
You need also Android SDK for android-19 platform (the API for Android 4.4) and You need also Android SDK for android-19 platform (the API for Android 4.4) and
Android NDK r12b. Android NDK. Note that NDK >= r15b is atm. not supported. Version r12b is
strongly recommended, because it's known that it works without issues.
You need to create proper "android-sdk" and "android-ndk" symlinks in the You need to create proper "android-sdk" and "android-ndk" symlinks in the
directory with Android project, so that the compilation script will have access directory with Android project, so that the compilation script will have access

View File

@ -19,7 +19,7 @@
################################################################################ ################################################################################
export KARTS="elephpant gnu nolok pidgin suzanne tux xue" export KARTS="all"
export TRACKS="battleisland cornfield_crossing featunlocked gplose gpwin \ export TRACKS="battleisland cornfield_crossing featunlocked gplose gpwin \
hacienda introcutscene introcutscene2 lighthouse olivermath \ hacienda introcutscene introcutscene2 lighthouse olivermath \
overworld sandtrack scotland snowmountain snowtuxpeak \ overworld sandtrack scotland snowmountain snowtuxpeak \
@ -42,6 +42,8 @@ export RUN_OPTIMIZE_SCRIPT=0
export DECREASE_QUALITY=1 export DECREASE_QUALITY=1
export CONVERT_TO_JPG=1 export CONVERT_TO_JPG=1
export CONVERT_TO_JPG_BLACKLIST="data/karts/hexley/hexley_kart_diffuse.png"
export BLACKLIST_FILES="data/music/cocoa_river_fast.ogg2" export BLACKLIST_FILES="data/music/cocoa_river_fast.ogg2"
################################################################################ ################################################################################
@ -52,21 +54,21 @@ cd "`dirname "$0"`"
# Find assets path # Find assets path
for ASSETS_PATH in $ASSETS_PATHS; do for ASSETS_PATH in $ASSETS_PATHS; do
if [ -d $ASSETS_PATH ] && [ `ls $ASSETS_PATH | grep -c tracks` -gt 0 ]; then if [ -d $ASSETS_PATH ] && [ `ls $ASSETS_PATH | grep -c tracks` -gt 0 ]; then
echo "Assets found in $ASSETS_PATH" echo "Assets found in $ASSETS_PATH"
ASSETS_PATH_FOUND=1 ASSETS_PATH_FOUND=1
break break
fi fi
done done
if [ -z $ASSETS_PATH_FOUND ]; then if [ -z $ASSETS_PATH_FOUND ]; then
echo "Couldn't find assets path" echo "Couldn't find assets path"
exit 1 exit 1
fi fi
if [ ! -d "../data" ]; then if [ ! -d "../data" ]; then
echo "Couldn't find data directory" echo "Couldn't find data directory"
exit 1 exit 1
fi fi
@ -81,27 +83,27 @@ echo "Copy all assets"
mkdir -p assets/data mkdir -p assets/data
for DIR in `ls $ASSETS_PATH`; do for DIR in `ls $ASSETS_PATH`; do
CAN_BE_COPIED=0 CAN_BE_COPIED=0
for ASSETS_DIR in $ASSETS_DIRS; do for ASSETS_DIR in $ASSETS_DIRS; do
if [ $DIR = $ASSETS_DIR ]; then if [ $DIR = $ASSETS_DIR ]; then
CAN_BE_COPIED=1 CAN_BE_COPIED=1
break break
fi fi
done; done;
# Don't copy karts and tracks. It will be handled later # Don't copy karts and tracks. It will be handled later
BLACKLIST_ASSETS="karts tracks" BLACKLIST_ASSETS="karts tracks"
for ASSETS_DIR in $BLACKLIST_ASSETS; do for ASSETS_DIR in $BLACKLIST_ASSETS; do
if [ $DIR = $ASSETS_DIR ]; then if [ $DIR = $ASSETS_DIR ]; then
CAN_BE_COPIED=0 CAN_BE_COPIED=0
break break
fi fi
done; done;
if [ $CAN_BE_COPIED -gt 0 ]; then if [ $CAN_BE_COPIED -gt 0 ]; then
cp -a "$ASSETS_PATH/$DIR" assets/data/ cp -a "$ASSETS_PATH/$DIR" assets/data/
fi fi
done; done;
@ -111,22 +113,22 @@ echo "Copy selected tracks"
mkdir -p assets/data/tracks mkdir -p assets/data/tracks
for DIR in `ls $ASSETS_PATH/tracks`; do for DIR in `ls $ASSETS_PATH/tracks`; do
CAN_BE_COPIED=0 CAN_BE_COPIED=0
if [ "$TRACKS" != "all" ]; then if [ "$TRACKS" != "all" ]; then
for TRACK in $TRACKS; do for TRACK in $TRACKS; do
if [ $DIR = $TRACK ]; then if [ $DIR = $TRACK ]; then
CAN_BE_COPIED=1 CAN_BE_COPIED=1
break break
fi fi
done; done;
else else
CAN_BE_COPIED=1 CAN_BE_COPIED=1
fi fi
if [ $CAN_BE_COPIED -gt 0 ]; then if [ $CAN_BE_COPIED -gt 0 ]; then
cp -a "$ASSETS_PATH/tracks/$DIR" assets/data/tracks/ cp -a "$ASSETS_PATH/tracks/$DIR" assets/data/tracks/
fi fi
done done
@ -136,22 +138,22 @@ echo "Copy selected karts"
mkdir -p assets/data/karts mkdir -p assets/data/karts
for DIR in `ls $ASSETS_PATH/karts`; do for DIR in `ls $ASSETS_PATH/karts`; do
CAN_BE_COPIED=0 CAN_BE_COPIED=0
if [ "$KARTS" != "all" ]; then if [ "$KARTS" != "all" ]; then
for KART in $KARTS; do for KART in $KARTS; do
if [ $DIR = $KART ]; then if [ $DIR = $KART ]; then
CAN_BE_COPIED=1 CAN_BE_COPIED=1
break break
fi fi
done; done;
else else
CAN_BE_COPIED=1 CAN_BE_COPIED=1
fi fi
if [ $CAN_BE_COPIED -gt 0 ]; then if [ $CAN_BE_COPIED -gt 0 ]; then
cp -a "$ASSETS_PATH/karts/$DIR" assets/data/karts/ cp -a "$ASSETS_PATH/karts/$DIR" assets/data/karts/
fi fi
done done
@ -160,263 +162,405 @@ echo "Decrease assets quality"
convert_image() convert_image()
{ {
if [ -z "$1" ]; then FILE="$1"
echo "No file to convert" FILE_TYPE="$2"
return echo "Convert file: $FILE"
fi
FILE="$1" if [ ! -f "$FILE" ]; then
FILE_TYPE="$2" echo " File doesn't exist."
return
fi
W=`identify -format "%[fx:w]" "$FILE"` W=`identify -format "%[fx:w]" "$FILE"`
H=`identify -format "%[fx:h]" "$FILE"` H=`identify -format "%[fx:h]" "$FILE"`
if [ -z $W ] || [ -z $H ]; then if [ -z $W ] || [ -z $H ]; then
echo "Couldn't convert $FILE file" echo "Couldn't convert $FILE file"
return return
fi fi
if [ $W -gt $TEXTURE_SIZE ] || [ $H -gt $TEXTURE_SIZE ]; then if [ $W -gt $TEXTURE_SIZE ] || [ $H -gt $TEXTURE_SIZE ]; then
if [ $W -gt $H ]; then if [ $W -gt $H ]; then
SCALED_W=$TEXTURE_SIZE SCALED_W=$TEXTURE_SIZE
SCALED_H=$(($TEXTURE_SIZE * $H / $W)) SCALED_H=$(($TEXTURE_SIZE * $H / $W))
else else
SCALED_W=$(($TEXTURE_SIZE * $W / $H)) SCALED_W=$(($TEXTURE_SIZE * $W / $H))
SCALED_H=$TEXTURE_SIZE SCALED_H=$TEXTURE_SIZE
fi fi
SCALE_CMD="-scale ${SCALED_W}x${SCALED_H}" SCALE_CMD="-scale ${SCALED_W}x${SCALED_H}"
fi fi
if [ "$FILE_TYPE" = "jpg" ]; then if [ "$FILE_TYPE" = "jpg" ]; then
QUALITY_CMD="-quality $JPEG_QUALITY" QUALITY_CMD="-quality $JPEG_QUALITY"
elif [ "$FILE_TYPE" = "png" ]; then elif [ "$FILE_TYPE" = "png" ]; then
QUALITY_CMD="-quality $PNG_QUALITY" QUALITY_CMD="-quality $PNG_QUALITY"
fi fi
convert $SCALE_CMD $QUALITY_CMD "$FILE" "tmp.$FILE_TYPE" convert $SCALE_CMD $QUALITY_CMD "$FILE" "tmp.$FILE_TYPE"
if [ -s "tmp.$FILE_TYPE" ]; then if [ -s "tmp.$FILE_TYPE" ]; then
SIZE_OLD=`du -k "$FILE" | cut -f1` SIZE_OLD=`du -k "$FILE" | cut -f1`
SIZE_NEW=`du -k "tmp.$FILE_TYPE" | cut -f1` SIZE_NEW=`du -k "tmp.$FILE_TYPE" | cut -f1`
if [ $SIZE_NEW -lt $SIZE_OLD ]; then if [ $SIZE_NEW -lt $SIZE_OLD ]; then
mv "tmp.$FILE_TYPE" "$FILE" mv "tmp.$FILE_TYPE" "$FILE"
fi fi
fi fi
rm -f "tmp.$FILE_TYPE" rm -f "tmp.$FILE_TYPE"
} }
convert_sound() convert_sound()
{ {
if [ -z "$1" ]; then FILE="$1"
echo "No file to convert" echo "Convert file: $FILE"
return
fi
FILE="$1" if [ ! -f "$FILE" ]; then
echo " File doesn't exist."
return
fi
oggdec "$FILE" -o tmp.wav oggdec "$FILE" -o tmp.wav
if [ -s tmp.wav ]; then if [ -s tmp.wav ]; then
OGGENC_CMD="" OGGENC_CMD=""
if [ "$SOUND_MONO" -gt 0 ]; then if [ "$SOUND_MONO" -gt 0 ]; then
OGGENC_CMD="$OGGENC_CMD --downmix" OGGENC_CMD="$OGGENC_CMD --downmix"
fi fi
OGG_RATE=`ogginfo "$FILE" | grep "Rate: " | cut -f 2 -d " " \ OGG_RATE=`ogginfo "$FILE" | grep "Rate: " | cut -f 2 -d " " \
| grep -o '[0-9]*'` | grep -o '[0-9]*'`
if [ ! -z "$OGG_RATE" ] && [ "$OGG_RATE" -gt "$SOUND_SAMPLE" ]; then if [ ! -z "$OGG_RATE" ] && [ "$OGG_RATE" -gt "$SOUND_SAMPLE" ]; then
OGGENC_CMD="$OGGENC_CMD --resample $SOUND_SAMPLE" OGGENC_CMD="$OGGENC_CMD --resample $SOUND_SAMPLE"
fi fi
OGGENC_CMD="$OGGENC_CMD -b $SOUND_QUALITY" OGGENC_CMD="$OGGENC_CMD -b $SOUND_QUALITY"
oggenc $OGGENC_CMD tmp.wav -o tmp.ogg oggenc $OGGENC_CMD tmp.wav -o tmp.ogg
fi fi
if [ -s tmp.ogg ]; then if [ -s tmp.ogg ]; then
SIZE_OLD=`du -k "$FILE" | cut -f1` SIZE_OLD=`du -k "$FILE" | cut -f1`
SIZE_NEW=`du -k "tmp.ogg" | cut -f1` SIZE_NEW=`du -k "tmp.ogg" | cut -f1`
if [ $SIZE_NEW -lt $SIZE_OLD ]; then if [ $SIZE_NEW -lt $SIZE_OLD ]; then
mv tmp.ogg "$FILE" mv tmp.ogg "$FILE"
fi fi
fi fi
rm -f tmp.wav tmp.ogg rm -f tmp.wav tmp.ogg
} }
convert_b3d() convert_to_jpg()
{ {
if [ -z "$1" ]; then FILE="$1"
echo "No file to convert" echo "Convert file: $FILE"
return
fi
FILE="$1" if [ ! -f "$FILE" ]; then
echo "Convert file: $FILE" echo " File doesn't exist."
return
fi
if [ ! -f "$FILE" ]; then ALREADY_CONVERTED=0
echo " File doesn't exist."
return
fi
HEX_FILE=`hexdump -ve '1/1 "%.2x"' "$FILE"` if [ -s "./converted_textures" ]; then
while read -r CONVERTED_TEXTURE; do
TEXS_CHUNK="54455853" if [ "$FILE" = "$CONVERTED_TEXTURE" ]; then
TEXS_CHUNK_POS=24 ALREADY_CONVERTED=1
break
FOUND_CHUNK=`echo $HEX_FILE | head -c $(($TEXS_CHUNK_POS + 8)) \
| tail -c +$(($TEXS_CHUNK_POS + 1))`
if [ -z "$FOUND_CHUNK" ] || [ "$FOUND_CHUNK" != "$TEXS_CHUNK" ]; then
echo " Unsupported format."
return
fi
TEXS_SIZE=`echo $HEX_FILE | head -c $(($TEXS_CHUNK_POS + 16)) | tail -c 8`
TEXS_SIZE_CONVERTED=`echo $TEXS_SIZE | cut -c7-8`
TEXS_SIZE_CONVERTED=$TEXS_SIZE_CONVERTED`echo $TEXS_SIZE | cut -c5-6`
TEXS_SIZE_CONVERTED=$TEXS_SIZE_CONVERTED`echo $TEXS_SIZE | cut -c3-4`
TEXS_SIZE_CONVERTED=$TEXS_SIZE_CONVERTED`echo $TEXS_SIZE | cut -c1-2`
TEXS_SIZE_CONVERTED=`echo $((0x$TEXS_SIZE_CONVERTED))`
if [ $TEXS_SIZE_CONVERTED -le 0 ]; then
echo " Invalid TEXS size value."
return
fi
TEXS_BEGIN=$(($TEXS_CHUNK_POS + 16))
TEXS_END=$(($TEXS_BEGIN + $TEXS_SIZE_CONVERTED * 2))
HEX_TEXS=`echo $HEX_FILE | head -c $TEXS_END | tail -c +$(($TEXS_BEGIN+1))`
CURR_POS=0
cp "$FILE" tmp.b3d
while [ $CURR_POS -lt $TEXS_END ]; do
NULL_POS=`echo $HEX_TEXS | tail -c +$(($CURR_POS+1)) | grep -b -o "00" \
| head -n 1 | cut -f1 -d":"`
if [ -z $NULL_POS ]; then
echo " Done."
break
fi
if [ $NULL_POS -lt 4 ]; then
echo " Something went wrong..."
break
fi
TEXNAME_BEGIN=$((($TEXS_BEGIN + $CURR_POS) / 2))
TEXNAME_END=$((($TEXS_BEGIN + $CURR_POS + $NULL_POS) / 2))
CURR_POS=$(($CURR_POS + $NULL_POS + 58))
TEXTURE_NAME=`dd if="$FILE" bs=1 skip=$TEXNAME_BEGIN \
count=$(($TEXNAME_END - $TEXNAME_BEGIN)) 2> /dev/null`
DIRNAME=`dirname "$FILE"`
TEXTURE_PATH="$DIRNAME/$TEXTURE_NAME"
echo " Texture: $TEXTURE_NAME"
ALREADY_CONVERTED=0
if [ -s "./converted_textures" ]; then
while read -r CONVERTED_TEXTURE; do
if [ "$TEXTURE_PATH" = "$CONVERTED_TEXTURE" ]; then
ALREADY_CONVERTED=1
break
fi fi
done < "./converted_textures" done < "./converted_textures"
fi fi
if [ $ALREADY_CONVERTED -eq 0 ]; then if [ $ALREADY_CONVERTED -eq 1 ]; then
if [ ! -f "$TEXTURE_PATH" ]; then return
echo " Couldn't find texture file. Ignore..." fi
BLACKLISTED=0
for BLACKLIST_FILE in $CONVERT_TO_JPG_BLACKLIST; do
if [ "$FILE" = "assets/$BLACKLIST_FILE" ]; then
BLACKLISTED=1
break
fi
done
if [ $BLACKLISTED -eq 1 ]; then
#echo " File is blacklisted. Ignore..."
continue
fi
FILE_EXTENSION=`echo "$FILE" | tail -c 5`
if [ `echo "$FILE_EXTENSION" | head -c 1` != "." ]; then
#echo " Unsupported file extension. Ignore..."
continue
fi
FILE_FORMAT=`identify -format %m "$FILE"`
if [ "$FILE_FORMAT" = "JPEG" ]; then
#echo " File is already JPEG. Ignore..."
continue
fi
IS_OPAQUE=`identify -format '%[opaque]' "$FILE"`
#HAS_ALPHA=`identify -format '%A' "$FILE"`
if [ "$IS_OPAQUE" = "False" ] || [ "$IS_OPAQUE" = "false" ]; then
#echo " File has alpha channel. Ignore..."
continue
fi
DIRNAME="`dirname "$FILE"`"
BASENAME="`basename "$FILE"`"
IS_GLOSS_MAP=`find "$DIRNAME" -iname "*.xml" -exec cat {} \; \
| grep -c "gloss-map=\"$BASENAME\""`
if [ $IS_GLOSS_MAP -gt 0 ]; then
#echo " File is a gloss-map. Ignore..."
continue
fi
NEW_FILE="`echo $FILE | head -c -5`.jpg"
if [ -f "$NEW_FILE" ]; then
#echo " There is already a file with .jpg extension. Ignore..."
continue
fi
# We can check if new file is smaller
convert -quality $JPEG_QUALITY "$FILE" "$NEW_FILE"
rm -f "$FILE"
echo "$FILE" >> "./converted_textures"
}
convert_to_jpg_extract_b3dz()
{
FILE="$1"
echo "Convert file: $FILE"
if [ ! -f "$FILE" ]; then
echo " File doesn't exist."
return
fi
DIRNAME="`dirname "$FILE"`"
unzip "$FILE" -d "$DIRNAME"
rm -f "$FILE"
TEXNAME="`basename "$FILE"`"
NEWNAME="`echo $TEXNAME | head -c -6`.b3d"
sed -i "s/\"$TEXNAME\"/\"$NEWNAME\"/g" "$DIRNAME/kart.xml"
}
convert_to_jpg_update_b3d()
{
FILE="$1"
echo "Convert file: $FILE"
if [ ! -f "$1" ]; then
echo " File doesn't exist."
return
fi
HEX_FILE=`hexdump -ve '1/1 "%.2x"' "$FILE"`
TEXS_CHUNK="54455853"
TEXS_CHUNK_POS=24
FOUND_CHUNK=`echo $HEX_FILE | head -c $(($TEXS_CHUNK_POS + 8)) \
| tail -c +$(($TEXS_CHUNK_POS + 1))`
if [ -z "$FOUND_CHUNK" ] || [ "$FOUND_CHUNK" != "$TEXS_CHUNK" ]; then
echo " File has no textures."
return
fi
TEXS_SIZE=`echo $HEX_FILE | head -c $(($TEXS_CHUNK_POS + 16)) | tail -c 8`
TEXS_SIZE_CONVERTED=`echo $TEXS_SIZE | cut -c7-8`
TEXS_SIZE_CONVERTED=$TEXS_SIZE_CONVERTED`echo $TEXS_SIZE | cut -c5-6`
TEXS_SIZE_CONVERTED=$TEXS_SIZE_CONVERTED`echo $TEXS_SIZE | cut -c3-4`
TEXS_SIZE_CONVERTED=$TEXS_SIZE_CONVERTED`echo $TEXS_SIZE | cut -c1-2`
TEXS_SIZE_CONVERTED=`echo $((0x$TEXS_SIZE_CONVERTED))`
if [ $TEXS_SIZE_CONVERTED -le 0 ]; then
echo " Invalid TEXS size value."
return
fi
TEXS_BEGIN=$(($TEXS_CHUNK_POS + 16))
TEXS_END=$(($TEXS_BEGIN + $TEXS_SIZE_CONVERTED * 2))
HEX_TEXS=`echo $HEX_FILE | head -c $TEXS_END | tail -c +$(($TEXS_BEGIN+1))`
CURR_POS=0
while [ $CURR_POS -lt $TEXS_END ]; do
NULL_POS=`echo $HEX_TEXS | tail -c +$(($CURR_POS+1)) | grep -b -o "00" \
| head -n 1 | cut -f1 -d":"`
if [ -z $NULL_POS ]; then
#echo " Done."
break
fi
if [ $NULL_POS -lt 4 ]; then
echo " Something went wrong..."
break
fi
TEXNAME_BEGIN=$((($TEXS_BEGIN + $CURR_POS) / 2))
TEXNAME_END=$((($TEXS_BEGIN + $CURR_POS + $NULL_POS) / 2))
CURR_POS=$(($CURR_POS + $NULL_POS + 58))
TEXTURE_NAME=`dd if="$FILE" bs=1 skip=$TEXNAME_BEGIN \
count=$(($TEXNAME_END - $TEXNAME_BEGIN)) 2> /dev/null`
DIRNAME="`dirname "$FILE"`"
TEXTURE_PATH="$DIRNAME/$TEXTURE_NAME"
IS_CONVERTED=0
while read -r CONVERTED_TEXTURE; do
if [ "$TEXTURE_PATH" = "$CONVERTED_TEXTURE" ]; then
IS_CONVERTED=1
break
fi
done < "./converted_textures"
if [ $IS_CONVERTED -eq 1 ]; then
echo -n ".jpg" | dd of="$FILE" bs=1 seek=$(($TEXNAME_END - 4)) \
conv=notrunc 2> /dev/null
fi;
done
}
convert_to_jpg_update_spm()
{
FILE="$1"
echo "Convert file: $FILE"
if [ ! -f "$1" ]; then
echo " File doesn't exist."
return
fi
HEX_FILE=`hexdump -ve '1/1 "%.2x"' "$FILE"`
SP_HEADER="5350"
SP_FOUND=`echo $HEX_FILE | head -c 4`
if [ -z "$SP_FOUND" ] || [ "$SP_FOUND" != "$SP_HEADER" ]; then
echo " Unsupported format."
return
fi
TEXS_BEGIN=60
TEXS_COUNT=`echo $HEX_FILE | head -c $TEXS_BEGIN | tail -c 4`
TEXS_COUNT_CONVERTED=`echo $TEXS_COUNT | cut -c3-4`
TEXS_COUNT_CONVERTED=$TEXS_COUNT_CONVERTED`echo $TEXS_COUNT | cut -c1-2`
TEXS_COUNT_CONVERTED=`echo $((0x$TEXS_COUNT_CONVERTED))`
TEXS_COUNT_CONVERTED=$(($TEXS_COUNT_CONVERTED * 2))
if [ $TEXS_COUNT_CONVERTED -le 0 ]; then
echo " Invalid textures count value."
return
fi
CURR_POS=$(($TEXS_BEGIN + 2))
while [ $TEXS_COUNT_CONVERTED -gt 0 ]; do
TEXS_COUNT_CONVERTED=$(($TEXS_COUNT_CONVERTED - 1))
TEX_LEN=`echo $HEX_FILE | head -c $(($CURR_POS)) | tail -c 2`
TEX_LEN=`echo $((0x$TEX_LEN))`
TEXNAME_BEGIN=$(($CURR_POS / 2))
TEXNAME_END=$(($CURR_POS / 2 + $TEX_LEN))
CURR_POS=$(($CURR_POS + 2 + $TEX_LEN * 2))
if [ $TEX_LEN -eq 0 ]; then
#echo " Empty texture name, ignore..."
continue continue
fi fi
FILE_EXTENSION=`echo "$TEXTURE_PATH" | tail -c 5` TEXTURE_NAME=`dd if="$FILE" bs=1 skip=$TEXNAME_BEGIN \
count=$(($TEXNAME_END - $TEXNAME_BEGIN)) 2> /dev/null`
if [ `echo "$FILE_EXTENSION" | head -c 1` != "." ]; then DIRNAME="`dirname "$FILE"`"
echo " Unsupported file extension. Ignore..." TEXTURE_PATH="$DIRNAME/$TEXTURE_NAME"
continue
fi
FILE_FORMAT=`identify -format %m "$TEXTURE_PATH"` IS_CONVERTED=0
if [ "$FILE_FORMAT" = "JPEG" ]; then while read -r CONVERTED_TEXTURE; do
echo " File is already JPEG. Ignore..." if [ "$TEXTURE_PATH" = "$CONVERTED_TEXTURE" ]; then
continue IS_CONVERTED=1
fi break
fi
done < "./converted_textures"
#IS_OPAQUE=`identify -format '%[opaque]' "$TEXTURE_PATH"` if [ $IS_CONVERTED -eq 1 ]; then
HAS_ALPHA=`identify -format '%A' "$TEXTURE_PATH"` echo -n ".jpg" | dd of="$FILE" bs=1 seek=$(($TEXNAME_END - 4)) \
conv=notrunc 2> /dev/null
fi
done
}
if [ "$HAS_ALPHA" = "True" ] || [ "$HAS_ALPHA" = "true" ]; then convert_to_jpg_update_xml()
echo " File has alpha channel. Ignore..." {
continue FILE="$1"
fi echo "Convert file: $FILE"
NEW_TEXTURE_NAME="`echo $TEXTURE_NAME | head -c -5`.jpg" if [ ! -f "$FILE" ]; then
NEW_TEXTURE_PATH="`echo $TEXTURE_PATH | head -c -5`.jpg" echo " File doesn't exist."
return
fi
if [ -f "$NEW_TEXTURE_PATH" ]; then DIRNAME="`dirname "$FILE"`"
echo " There is already a file with .jpg extension. Ignore..."
continue
fi
convert -quality $JPEG_QUALITY "$TEXTURE_PATH" "$NEW_TEXTURE_PATH" while read -r CONVERTED_TEXTURE; do
rm -f "$TEXTURE_PATH" DIRNAME_TEX="`dirname "$CONVERTED_TEXTURE"`"
if [ -s "$DIRNAME/materials.xml" ]; then if [ "$DIRNAME_TEX" != "$DIRNAME" ]; then
sed -i "s/name=\"$TEXTURE_NAME\"/name=\"$NEW_TEXTURE_NAME\"/g" \ continue;
"$DIRNAME/materials.xml" fi
fi
if [ -s "$DIRNAME/scene.xml" ]; then TEXNAME="`basename "$CONVERTED_TEXTURE" | head -c -5`"
sed -i "s/name=\"$TEXTURE_NAME\"/name=\"$NEW_TEXTURE_NAME\"/g" \
"$DIRNAME/scene.xml"
fi
echo "$TEXTURE_PATH" >> "./converted_textures" sed -i "s/\"$TEXNAME.[pP][nN][gG]/\"$TEXNAME.jpg/g" "$FILE"
fi sed -i "s/ $TEXNAME.[pP][nN][gG]/ $TEXNAME.jpg/g" "$FILE"
done < "./converted_textures"
echo -n ".jpg" | dd of=./tmp.b3d bs=1 seek=$(($TEXNAME_END - 4)) \
conv=notrunc 2> /dev/null
done
SIZE_OLD=`du -b "$FILE" | cut -f1`
SIZE_NEW=`du -b "tmp.b3d" | cut -f1`
if [ $SIZE_NEW -ne $SIZE_OLD ]; then
echo " Something went wrong..."
exit
fi
mv tmp.b3d "$FILE"
} }
if [ $DECREASE_QUALITY -gt 0 ]; then if [ $DECREASE_QUALITY -gt 0 ]; then
find assets/data -iname "*.png" | while read f; do convert_image "$f" "png"; done find assets/data -iname "*.png" | while read f; do convert_image "$f" "png"; done
find assets/data -iname "*.jpg" | while read f; do convert_image "$f" "jpg"; done find assets/data -iname "*.jpg" | while read f; do convert_image "$f" "jpg"; done
find assets/data -iname "*.ogg" | while read f; do convert_sound "$f"; done find assets/data -iname "*.ogg" | while read f; do convert_sound "$f"; done
fi fi
if [ $CONVERT_TO_JPG -gt 0 ]; then if [ $CONVERT_TO_JPG -gt 0 ]; then
find assets/data -iname "*.b3d" | while read f; do convert_b3d "$f"; done rm -f "./converted_textures"
if [ -s "./converted_textures" ]; then find assets/data -not -path "assets/data/textures/*" -iname "*.png" | while read f; do convert_to_jpg "$f"; done
echo "Converted textures:"
cat "./converted_textures" find assets/data -iname "*.b3dz" | while read f; do convert_to_jpg_extract_b3dz "$f"; done
rm -f "./converted_textures" find assets/data -iname "*.b3d" | while read f; do convert_to_jpg_update_b3d "$f"; done
fi find assets/data -iname "*.spm" | while read f; do convert_to_jpg_update_spm "$f"; done
find assets/data -iname "*.xml" | while read f; do convert_to_jpg_update_xml "$f"; done
if [ -s "./converted_textures" ]; then
echo "Converted textures:"
cat "./converted_textures"
rm -f "./converted_textures"
fi
fi fi
@ -427,14 +571,14 @@ cp -a ../data/* assets/data/
# Remove unused files # Remove unused files
for BLACKLIST_FILE in $BLACKLIST_FILES; do for BLACKLIST_FILE in $BLACKLIST_FILES; do
rm -f "assets/$BLACKLIST_FILE" rm -f "assets/$BLACKLIST_FILE"
done done
# Run optimize_data.sh script # Run optimize_data.sh script
if [ $RUN_OPTIMIZE_SCRIPT -gt 0 ]; then if [ $RUN_OPTIMIZE_SCRIPT -gt 0 ]; then
echo "Run optimize_data.sh script" echo "Run optimize_data.sh script"
sh -c 'cd assets/data; ../../../data/optimize_data.sh' sh -c 'cd assets/data; ../../../data/optimize_data.sh'
fi fi

18
cmake/FindEGL.cmake Normal file
View File

@ -0,0 +1,18 @@
# - Find EGL
# Find the EGL includes and libraries
#
# Following variables are provided:
# EGL_FOUND
# True if EGL has been found
# EGL_INCLUDE_DIR
# The include directory of EGL
# EGL_LIBRARY
# EGL library list
find_path(EGL_INCLUDE_DIR EGL/egl.h)
find_library(EGL_LIBRARY NAMES EGL)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(EGL DEFAULT_MSG EGL_LIBRARY EGL_INCLUDE_DIR)
mark_as_advanced(EGL_LIBRARY EGL_INCLUDE_DIR)

52
cmake/FindWayland.cmake Normal file
View File

@ -0,0 +1,52 @@
# - Find Wayland
# Find the Wayland includes and libraries
#
# Following variables are provided:
# WAYLAND_FOUND
# True if Wayland has been found
# WAYLAND_INCLUDE_DIRS
# The include directories of Wayland
# WAYLAND_LIBRARIES
# Wayland library list
find_path(WAYLAND_CLIENT_INCLUDE_DIR wayland-client.h)
find_path(WAYLAND_CURSOR_INCLUDE_DIR wayland-cursor.h)
find_path(WAYLAND_EGL_INCLUDE_DIR wayland-egl.h)
find_path(XKBCOMMON_INCLUDE_DIR xkbcommon/xkbcommon.h)
find_library(WAYLAND_CLIENT_LIBRARY NAMES wayland-client)
find_library(WAYLAND_CURSOR_LIBRARY NAMES wayland-cursor)
find_library(WAYLAND_EGL_LIBRARY NAMES wayland-egl)
find_library(XKBCOMMON_LIBRARY NAMES xkbcommon)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Wayland DEFAULT_MSG WAYLAND_CLIENT_LIBRARY
WAYLAND_CURSOR_LIBRARY
WAYLAND_EGL_LIBRARY
XKBCOMMON_LIBRARY
WAYLAND_CLIENT_INCLUDE_DIR
WAYLAND_CURSOR_INCLUDE_DIR
WAYLAND_EGL_INCLUDE_DIR
XKBCOMMON_INCLUDE_DIR)
set(WAYLAND_INCLUDE_DIRS ${WAYLAND_CLIENT_INCLUDE_DIR}
${WAYLAND_CURSOR_INCLUDE_DIR}
${WAYLAND_EGL_INCLUDE_DIR}
${XKBCOMMON_INCLUDE_DIR})
set(WAYLAND_LIBRARIES ${WAYLAND_CLIENT_LIBRARY}
${WAYLAND_CURSOR_LIBRARY}
${WAYLAND_EGL_LIBRARY}
${XKBCOMMON_LIBRARY})
list(REMOVE_DUPLICATES WAYLAND_INCLUDE_DIRS)
list(REMOVE_DUPLICATES WAYLAND_LIBRARIES)
mark_as_advanced(WAYLAND_CLIENT_LIBRARY
WAYLAND_CURSOR_LIBRARY
WAYLAND_EGL_LIBRARY
XKBCOMMON_LIBRARY
WAYLAND_CLIENT_INCLUDE_DIR
WAYLAND_CURSOR_INCLUDE_DIR
WAYLAND_EGL_INCLUDE_DIR
XKBCOMMON_INCLUDE_DIR)

View File

@ -1,18 +0,0 @@
find_path(XRANDR_INCLUDE_DIR NAMES X11/extensions/Xrandr.h
PATH_SUFFIXES X11/extensions
DOC "The XRANDR include directory"
)
find_library(XRANDR_LIBRARY NAMES Xrandr
DOC "The XRANDR library"
)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(XRANDR DEFAULT_MSG XRANDR_LIBRARY XRANDR_INCLUDE_DIR)
if(XRANDR_FOUND)
set( XRANDR_LIBRARIES ${XRANDR_LIBRARY} )
set( XRANDR_INCLUDE_DIRS ${XRANDR_INCLUDE_DIR} )
endif()
mark_as_advanced(XRANDR_INCLUDE_DIR XRANDR_LIBRARY)

View File

@ -10,7 +10,7 @@ SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++-posix)
SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres) SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres)
# figure out folder to look in # figure out folder to look in
execute_process(COMMAND sh -c "ls /usr/lib/gcc/x86_64-w64-mingw32/ | grep posix | tr -d '\n'" OUTPUT_VARIABLE MINGW_DEPS_FOLDER) execute_process(COMMAND sh -c "ls /usr/lib/gcc/i686-w64-mingw32/ | grep posix | tr -d '\n'" OUTPUT_VARIABLE MINGW_DEPS_FOLDER)
# here is the target environment located # here is the target environment located
SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32 /usr/lib/gcc/i686-w64-mingw32/${MINGW_DEPS_FOLDER}/ ${PROJECT_SOURCE_DIR}/dependencies) SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32 /usr/lib/gcc/i686-w64-mingw32/${MINGW_DEPS_FOLDER}/ ${PROJECT_SOURCE_DIR}/dependencies)

View File

@ -2,7 +2,7 @@
<achievements> <achievements>
<achievement id="1" check-type="all-at-least" reset-type="never" <achievement id="1" check-type="all-at-least" reset-type="never"
name="Christoffel Columbus" description="Play every official track at least once." > name="Christoffel Columbus" description="Play every official track at least once." >
<city goal="1"/> <candela_city goal="1"/>
<cocoa_temple goal="1"/> <cocoa_temple goal="1"/>
<cornfield_crossing goal="1"/> <cornfield_crossing goal="1"/>
<fortmagma goal="1"/> <fortmagma goal="1"/>
@ -22,6 +22,7 @@
<abyss goal="1"/> <abyss goal="1"/>
<xr591 goal="1"/> <xr591 goal="1"/>
<zengarden goal="1"/> <zengarden goal="1"/>
<volcano_island goal="1"/>
</achievement> </achievement>
<achievement id="2" check-type="all-at-least" reset-type="never" <achievement id="2" check-type="all-at-least" reset-type="never"
name="Strike!" description="Hit 10 karts with a bowling-ball."> name="Strike!" description="Hit 10 karts with a bowling-ball.">

View File

@ -1,6 +1,6 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="2">
<track id="city" laps="3"/> <track id="candela_city" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="70"/> <requirements trophies="70"/>

View File

@ -18,8 +18,8 @@
max="1200" /> max="1200" />
<!-- Size of the particles --> <!-- Size of the particles -->
<size min="0.65" <size min="0.60"
max="0.95" max="0.85"
x-increase-factor="0.6" x-increase-factor="0.6"
y-increase-factor="0.6" y-increase-factor="0.6"
/> />

View File

@ -18,8 +18,8 @@
max="1200" /> max="1200" />
<!-- Size of the particles --> <!-- Size of the particles -->
<size min="0.65" <size min="0.60"
max="0.95" max="0.85"
x-increase-factor="0.6" x-increase-factor="0.6"
y-increase-factor="0.6" y-increase-factor="0.6"
/> />

View File

@ -18,8 +18,8 @@
max="1200" /> max="1200" />
<!-- Size of the particles --> <!-- Size of the particles -->
<size min="0.65" <size min="0.60"
max="0.95" max="0.85"
x-increase-factor="0.6" x-increase-factor="0.6"
y-increase-factor="0.6" y-increase-factor="0.6"
/> />

View File

@ -18,8 +18,8 @@
max="500" /> max="500" />
<!-- Size of the particles --> <!-- Size of the particles -->
<size min="0.6" <size min="0.55"
max="0.8" /> max="0.75" />
<color min="255 255 255" <color min="255 255 255"
max="255 255 255" /> max="255 255 255" />

View File

@ -39,4 +39,5 @@
<card os="android" disable="ColorBufferFloat"/> <card os="android" disable="ColorBufferFloat"/>
<card contains="Adreno" os="android" version="<=19" disable="VertexIdWorking"/> <card contains="Adreno" os="android" version="<=19" disable="VertexIdWorking"/>
<card contains="Android Emulator" os="android" disable="ForceLegacyDevice"/> <card contains="Android Emulator" os="android" disable="ForceLegacyDevice"/>
<card os="android" disable="UniformBufferObject"/>
</graphical-restrictions> </graphical-restrictions>

View File

@ -28,6 +28,10 @@ Gauge and bar by Totoplus62, released under CC-BY-SA 3
menu_story by tavariz91, released under CC-0 menu_story by tavariz91, released under CC-0
mass.png by Auria, released under CC-0
power.png by Auria, based on https://openclipart.org/detail/193925/check-engine and https://openclipart.org/detail/144799/power-icon, released under CC-0
==== ====
Glass Skin by Auria, under CC-BY-SA 3+ Glass Skin by Auria, under CC-BY-SA 3+

View File

@ -132,16 +132,6 @@
<spacer height="4" width="10" /> <spacer height="4" width="10" />
<div layout="horizontal-row" proportion="1" height="fit">
<checkbox id="anim_gfx"/>
<spacer width="10" height="10"/>
<label text="Animated Scenery" I18N="Video settings"/>
</div>
</div>
<spacer height="4" width="10" />
<div layout="horizontal-row" width="100%" proportion="1">
<div layout="horizontal-row" proportion="1" height="fit"> <div layout="horizontal-row" proportion="1" height="fit">
<checkbox id="texture_compression"/> <checkbox id="texture_compression"/>
<spacer width="10" height="10"/> <spacer width="10" height="10"/>
@ -151,6 +141,14 @@
<spacer height="20" width="10" /> <spacer height="20" width="10" />
<div layout="horizontal-row" width="100%" proportion="1">
<label text="Animated Scenery" I18N="Video settings" width="40%"/>
<spacer width="10" height="10"/>
<gauge id="anim_gfx" min_value="0" max_value="2" width="50%" />
</div>
<spacer height="4" width="10" />
<div layout="horizontal-row" width="100%" proportion="1"> <div layout="horizontal-row" width="100%" proportion="1">
<label text="Animated Characters" I18N="Video settings" width="40%"/> <label text="Animated Characters" I18N="Video settings" width="40%"/>
<spacer width="10" height="10"/> <spacer width="10" height="10"/>

BIN
data/gui/mass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -42,7 +42,7 @@
<label width="100%" I18N="In the multitouch settings screen" text="Advanced"/> <label width="100%" I18N="In the multitouch settings screen" text="Advanced"/>
<div width="75%" layout="horizontal-row" proportion="1"> <div width="75%" layout="horizontal-row" proportion="1">
<label proportion="1" align="center" text_align="right" I18N="In the multitouch settings screen" text="Deadzone center"/> <label proportion="1" align="center" text_align="right" I18N="In the multitouch settings screen" text="Deadzone"/>
<div proportion="1" align="center" height="fit" layout="horizontal-row" > <div proportion="1" align="center" height="fit" layout="horizontal-row" >
<spacer width="40" height="10" /> <spacer width="40" height="10" />
<gauge id="deadzone_center" proportion="1" min_value="0" max_value="50"/> <gauge id="deadzone_center" proportion="1" min_value="0" max_value="50"/>
@ -50,7 +50,7 @@
</div> </div>
<div width="75%" layout="horizontal-row" proportion="1"> <div width="75%" layout="horizontal-row" proportion="1">
<label proportion="1" align="center" text_align="right" I18N="In the multitouch settings screen" text="Deadzone edge"/> <label proportion="1" align="center" text_align="right" I18N="In the multitouch settings screen" text="Sensitivity"/>
<div proportion="1" align="center" height="fit" layout="horizontal-row" > <div proportion="1" align="center" height="fit" layout="horizontal-row" >
<spacer width="40" height="10" /> <spacer width="40" height="10" />
<gauge id="deadzone_edge" proportion="1" min_value="0" max_value="50"/> <gauge id="deadzone_edge" proportion="1" min_value="0" max_value="50"/>

BIN
data/gui/power.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
data/gui/speed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@ -1,15 +1,15 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<items> <items>
<bonus-box model="gift-box.b3d" lowmodel="gift-box-low.b3d" glow="31 202 253"/> <bonus-box model="gift-box.spm" lowmodel="gift-box-low.spm" glow="31 202 253"/>
<banana model="banana.b3d" lowmodel="banana-low.b3d" glow="197 152 37"/> <banana model="banana.spm" lowmodel="banana-low.spm" glow="197 152 37"/>
<nitro-big model="nitrotank-big.b3d" lowmodel="nitrotank-big-low.b3d" glow="0 70 158"/> <nitro-big model="nitrotank-big.spm" lowmodel="nitrotank-big-low.spm" glow="0 70 158"/>
<nitro-small model="nitrotank-small.b3d" lowmodel="nitrotank-small-low.b3d" glow="0 70 158"/> <nitro-small model="nitrotank-small.spm" lowmodel="nitrotank-small-low.spm" glow="0 70 158"/>
<!-- While a bubble gum technically <!-- While a bubble gum technically
isn't an item, it is internally isn't an item, it is internally
handled as one, so list it here --> handled as one, so list it here -->
<bubblegum model="bubblegum.b3d" lowmodel="bubblegum-low.b3d" glow="246 150 209"/> <bubblegum model="bubblegum.spm" lowmodel="bubblegum-low.spm" glow="246 150 209"/>
<bubblegum-nolok model="bubblegum-nolok.b3d" lowmodel="bubblegum-nolok-low.b3d"/> <bubblegum-nolok model="bubblegum-nolok.spm" lowmodel="bubblegum-nolok-low.spm"/>
<!-- <easter-egg model="easter_egg.b3d" /> --> <!-- <easter-egg model="easter_egg.spm" /> -->
<easter-egg model="easter_egg.b3d" /> <easter-egg model="easter_egg.spm" />
</items> </items>

View File

@ -55,7 +55,7 @@
chassis-angular-damping="0" chassis-angular-damping="0"
downward-impulse-factor="5" downward-impulse-factor="5"
track-connection-accel="2" track-connection-accel="2"
angular-factor="0.5 1.0 0.5" angular-factor="0.25 1.0 0.5"
smooth-flying-impulse="250" /> smooth-flying-impulse="250" />
<!-- Turning <!-- Turning

File diff suppressed because it is too large Load Diff

View File

@ -2,17 +2,17 @@
<powerup> <powerup>
<item name="zipper" icon="zipper_collect.png" /> <item name="zipper" icon="zipper_collect.png" />
<item name="bowling" icon="bowling-icon.png" <item name="bowling" icon="bowling-icon.png"
model="bowling.b3d" speed="4.0" model="bowling.spm" speed="4.0"
min-height="0.2" max-height="1.0" min-height="0.2" max-height="1.0"
force-updown="1" force-to-target="40" force-updown="1" force-to-target="40"
max-distance="25" /> max-distance="25" />
<item name="bubblegum" icon="bubblegum-icon.png" /> <item name="bubblegum" icon="bubblegum-icon.png" />
<item name="cake" icon="cake-icon.png" <item name="cake" icon="cake-icon.png"
model="cake.b3d" speed="50" model="cake.spm" speed="50"
min-height="0.2" max-height="1.0" min-height="0.2" max-height="1.0"
force-updown="25" max-distance="90" /> force-updown="25" max-distance="90" />
<item name="anchor" icon="anchor-icon.png" <item name="anchor" icon="anchor-icon.png"
model="anchor.b3d" /> model="anchor.spm" />
<item name="switch" icon="swap-icon.png" /> <item name="switch" icon="swap-icon.png" />
<item name="swatter" icon="swatter-icon.png" /> <item name="swatter" icon="swatter-icon.png" />
<!-- interval: How long a single bounce takes. <!-- interval: How long a single bounce takes.
@ -56,7 +56,7 @@
tunneling. tunneling.
--> -->
<item name="rubber-ball" icon="rubber_ball-icon.png" <item name="rubber-ball" icon="rubber_ball-icon.png"
model="rubber_ball.b3d" speed="35.0" model="rubber_ball.spm" speed="35.0"
scale="1 1 1" interval="1" scale="1 1 1" interval="1"
max-height="4.0" min-height="0" max-height="4.0" min-height="0"
fast-ping-distance="50" fast-ping-distance="50"
@ -67,9 +67,9 @@
squash-slowdown="0.5" squash-duration="2" squash-slowdown="0.5" squash-duration="2"
delete-time="5.0" max-height-difference="10" /> delete-time="5.0" max-height-difference="10" />
<item name="parachute" icon="parachute-icon.png" <item name="parachute" icon="parachute-icon.png"
model="parachute.b3d" /> model="parachute.spm" />
<item name="plunger" icon="plunger-icon.png" <item name="plunger" icon="plunger-icon.png"
model="plunger.b3d" speed="35" model="plunger.spm" speed="35"
min-height="0.2" max-height="1.0" min-height="0.2" max-height="1.0"
force-updown="35" force-to-target="15" force-updown="35" force-to-target="15"
max-distance="25" /> max-distance="25" />

View File

@ -1,10 +1,12 @@
uniform sampler2D tex; uniform sampler2D tex;
in vec2 uv; in vec2 uv;
in vec4 vertex_color;
out vec4 FragColor; out vec4 FragColor;
void main(void) void main(void)
{ {
vec4 color = texture(tex, uv); vec4 color = texture(tex, uv);
color *= vertex_color;
FragColor = vec4(color.a * color.rgb, color.a); FragColor = vec4(color.a * color.rgb, color.a);
} }

View File

@ -1,4 +1,4 @@
uniform mat4 ModelViewMatrix; uniform mat4 color_matrix;
uniform vec3 Position; uniform vec3 Position;
uniform vec2 Size; uniform vec2 Size;
@ -11,10 +11,12 @@ in vec2 Texcoord;
#endif #endif
out vec2 uv; out vec2 uv;
out vec4 vertex_color;
void main(void) void main(void)
{ {
uv = Texcoord; uv = Texcoord;
vec4 Center = ModelViewMatrix * vec4(Position, 1.); vec4 Center = ViewMatrix * vec4(Position, 1.);
gl_Position = ProjectionMatrix * (Center + vec4(Size * Corner, 0., 0.)); gl_Position = ProjectionMatrix * (Center + vec4(Size * Corner, 0., 0.));
vertex_color = color_matrix[gl_VertexID];
} }

View File

@ -6,7 +6,6 @@ uniform vec2 dir;
uniform vec2 dir2; uniform vec2 dir2;
in vec2 uv; in vec2 uv;
in vec2 uv_bis;
in float camdist; in float camdist;
out vec4 FragColor; out vec4 FragColor;

View File

@ -1,22 +0,0 @@
uniform mat4 ModelMatrix;
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 3) in vec2 Texcoord;
layout(location = 4) in vec2 SecondTexcoord;
#else
in vec3 Position;
in vec2 Texcoord;
in vec2 SecondTexcoord;
#endif
out vec2 uv;
out vec2 uv_bis;
out float camdist;
void main() {
gl_Position = ProjectionViewMatrix * ModelMatrix * vec4(Position, 1.);
uv = Texcoord;
uv_bis = SecondTexcoord;
camdist = length(ViewMatrix * ModelMatrix * vec4(Position, 1.));
}

View File

@ -22,7 +22,7 @@ float anglespeed;
out float lf; out float lf;
out vec2 tc; out vec2 tc;
out vec3 pc; out vec4 pc;
void main(void) void main(void)
{ {
@ -68,5 +68,5 @@ void main(void)
vec4 viewpos = ViewMatrix * vec4(newposition + newquadcorner, 1.0); vec4 viewpos = ViewMatrix * vec4(newposition + newquadcorner, 1.0);
gl_Position = ProjectionMatrix * viewpos; gl_Position = ProjectionMatrix * viewpos;
pc = vec3(1.); pc = vec4(1.);
} }

View File

@ -20,7 +20,7 @@ out vec2 uv;
void main() void main()
{ {
vec3 test = sin(windDir * (Position.y* 0.5)) * 0.5; vec3 test = sin(windDir * (Position.y * 0.1)) * 1.;
test += cos(windDir) * 0.7; test += cos(windDir) * 0.7;
mat4 new_model_matrix = ModelMatrix; mat4 new_model_matrix = ModelMatrix;

View File

@ -1,11 +1,9 @@
#ifdef Use_Bindless_Texture #ifdef Use_Bindless_Texture
layout(bindless_sampler) uniform sampler2D Albedo; layout(bindless_sampler) uniform sampler2D Albedo;
layout(bindless_sampler) uniform sampler2D dtex;
layout(bindless_sampler) uniform sampler2D SpecMap; layout(bindless_sampler) uniform sampler2D SpecMap;
layout(bindless_sampler) uniform sampler2D colorization_mask; layout(bindless_sampler) uniform sampler2D colorization_mask;
#else #else
uniform sampler2D Albedo; uniform sampler2D Albedo;
uniform sampler2D dtex;
uniform sampler2D SpecMap; uniform sampler2D SpecMap;
uniform sampler2D colorization_mask; uniform sampler2D colorization_mask;
#endif #endif
@ -36,25 +34,8 @@ void main(void)
vec2 new_xy = mix(vec2(old_hsv.x, old_hsv.y), vec2(color_change.x, max(old_hsv.y, color_change.y)), vec2(mask_step, mask_step)); vec2 new_xy = mix(vec2(old_hsv.x, old_hsv.y), vec2(color_change.x, max(old_hsv.y, color_change.y)), vec2(mask_step, mask_step));
color.xyz = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z)); color.xyz = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z));
} }
vec2 texc = gl_FragCoord.xy / screen;
float z = texture(dtex, texc).x;
vec4 xpos = 2.0 * vec4(texc, z, 1.0) - 1.0f;
xpos = InverseProjectionMatrix * xpos;
xpos /= xpos.w;
vec3 eyedir = normalize(xpos.xyz);
// Inspired from http://http.developer.nvidia.com/GPUGems3/gpugems3_ch16.html
vec3 L = normalize((transpose(InverseViewMatrix) * vec4(sun_direction, 0.)).xyz);
float fEdotL = clamp(dot(L, eyedir), 0., 1.);
float fPowEdotL = pow(fEdotL, 4.);
float fLdotNBack = max(0., - dot(nor, L) * 0.6 + 0.4);
float scattering = mix(fPowEdotL, fLdotNBack, .5);
float specmap = texture(SpecMap, uv).g; float specmap = texture(SpecMap, uv).g;
float emitmap = texture(SpecMap, uv).b; float emitmap = texture(SpecMap, uv).b;
vec3 LightFactor = color.xyz * (scattering * 0.1) + getLightFactor(color.xyz, vec3(1.), specmap, emitmap); vec3 LightFactor = getLightFactor(color.xyz, vec3(1.), specmap, emitmap);
FragColor = vec4(LightFactor, 1.); FragColor = vec4(LightFactor, 1.);
} }

View File

@ -41,7 +41,7 @@ flat out sampler2D thirdhandle;
void main() void main()
{ {
vec3 test = sin(windDir * (Position.y* 0.5)) * 0.5; vec3 test = sin(windDir * (Position.y * 0.1)) * 1.;
test += cos(windDir) * 0.7; test += cos(windDir) * 0.7;
mat4 ModelMatrix = getWorldMatrix(Origin + test * Color.r, Orientation, Scale); mat4 ModelMatrix = getWorldMatrix(Origin + test * Color.r, Orientation, Scale);
mat4 TransposeInverseModelView = transpose(getInverseWorldMatrix(Origin + test * Color.r, Orientation, Scale) * InverseViewMatrix); mat4 TransposeInverseModelView = transpose(getInverseWorldMatrix(Origin + test * Color.r, Orientation, Scale) * InverseViewMatrix);

View File

@ -1,9 +1,6 @@
#ifdef Use_Bindless_Texture #ifndef Use_Bindless_Texture
layout(bindless_sampler) uniform sampler2D dtex;
#else
uniform sampler2D Albedo; uniform sampler2D Albedo;
uniform sampler2D SpecMap; uniform sampler2D SpecMap;
uniform sampler2D dtex;
uniform sampler2D colorization_mask; uniform sampler2D colorization_mask;
#endif #endif
@ -45,24 +42,6 @@ void main(void)
vec2 new_xy = mix(vec2(old_hsv.x, old_hsv.y), vec2(color_change.x, max(old_hsv.y, color_change.y)), vec2(mask_step, mask_step)); vec2 new_xy = mix(vec2(old_hsv.x, old_hsv.y), vec2(color_change.x, max(old_hsv.y, color_change.y)), vec2(mask_step, mask_step));
color.xyz = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z)); color.xyz = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z));
} }
vec3 LightFactor = getLightFactor(color.xyz, vec3(1.), specmap, emitmap);
vec2 texc = gl_FragCoord.xy / screen;
float z = texture(dtex, texc).x;
vec4 xpos = 2.0 * vec4(texc, z, 1.0) - 1.0f;
xpos = InverseProjectionMatrix * xpos;
xpos /= xpos.w;
vec3 eyedir = normalize(xpos.xyz);
// Inspired from http://http.developer.nvidia.com/GPUGems3/gpugems3_ch16.html
vec3 L = normalize((transpose(InverseViewMatrix) * vec4(sun_direction, 0.)).xyz);
float fEdotL = clamp(dot(L, eyedir), 0., 1.);
float fPowEdotL = pow(fEdotL, 4.);
float fLdotNBack = max(0., - dot(nor, L) * 0.6 + 0.4);
float scattering = mix(fPowEdotL, fLdotNBack, .5);
vec3 LightFactor = color.xyz * (scattering * 0.1) + getLightFactor(color.xyz, vec3(1.), specmap, emitmap);
FragColor = vec4(LightFactor, 1.); FragColor = vec4(LightFactor, 1.);
} }

View File

@ -41,7 +41,7 @@ out vec3 bitangent;
out vec2 uv; out vec2 uv;
out vec2 uv_bis; out vec2 uv_bis;
out vec4 color; out vec4 color;
out float camdist;
void main(void) void main(void)
{ {
@ -56,4 +56,5 @@ void main(void)
bitangent = (ViewMatrix * ModelMatrix * vec4(Bitangent, 0.)).xyz; bitangent = (ViewMatrix * ModelMatrix * vec4(Bitangent, 0.)).xyz;
uv = vec2(Texcoord.x + texture_trans.x, Texcoord.y + texture_trans.y); uv = vec2(Texcoord.x + texture_trans.x, Texcoord.y + texture_trans.y);
uv_bis = SecondTexcoord; uv_bis = SecondTexcoord;
camdist = length(ViewMatrix * ModelMatrix * vec4(Position, 1.));
} }

View File

@ -4,7 +4,7 @@ uniform mat4 invproj;
in float lf; in float lf;
in vec2 tc; in vec2 tc;
in vec3 pc; in vec4 pc;
out vec4 FragColor; out vec4 FragColor;
#stk_include "utils/getPosFromUVDepth.frag" #stk_include "utils/getPosFromUVDepth.frag"
@ -17,6 +17,5 @@ void main(void)
float EnvZ = texture(dtex, xy).x; float EnvZ = texture(dtex, xy).x;
vec4 EnvPos = getPosFromUVDepth(vec3(xy, EnvZ), InverseProjectionMatrix); vec4 EnvPos = getPosFromUVDepth(vec3(xy, EnvZ), InverseProjectionMatrix);
float alpha = clamp((EnvPos.z - FragmentPos.z) * 0.3, 0., 1.); float alpha = clamp((EnvPos.z - FragmentPos.z) * 0.3, 0., 1.);
vec4 color = texture(tex, tc) * vec4(pc, 1.0); FragColor = texture(tex, tc) * pc * alpha;
FragColor = color * alpha * smoothstep(1., 0.8, lf);
} }

View File

@ -19,13 +19,16 @@ in vec2 quadcorner;
out float lf; out float lf;
out vec2 tc; out vec2 tc;
out vec3 pc; out vec4 pc;
void main(void) void main(void)
{ {
tc = Texcoord; tc = Texcoord;
lf = lifetime; lf = lifetime;
pc = color_from + (color_to - color_from) * lifetime; pc = vec4(vec3(color_from + (color_to - color_from) * lf), 1.0) * smoothstep(1., 0.8, lf);
#if defined(GL_ES) && !defined(Advanced_Lighting_Enabled)
pc.rgb = pow(pc.rgb, vec3(1. / 2.2));
#endif
vec3 newposition = Position; vec3 newposition = Position;
vec4 viewpos = ViewMatrix * vec4(newposition, 1.0); vec4 viewpos = ViewMatrix * vec4(newposition, 1.0);

View File

@ -3,11 +3,11 @@
<config> <config>
<!-- Minimum and maximum kart versions that can be used by this binary. <!-- Minimum and maximum kart versions that can be used by this binary.
Older version will be ignored. --> Older version will be ignored. -->
<kart-version min="2" max="2"/> <kart-version min="2" max="3"/>
<!-- Minimum and maxium track versions that be be read by this binary. <!-- Minimum and maxium track versions that be be read by this binary.
Older versions will be ignored. --> Older versions will be ignored. -->
<track-version min="6" max="6"/> <track-version min="6" max="7"/>
<!-- Maximum number of karts to be used at the same time. This limit <!-- Maximum number of karts to be used at the same time. This limit
can easily be increased, but some tracks might not have valid start can easily be increased, but some tracks might not have valid start
@ -406,8 +406,8 @@
behaviour of the karts. --> behaviour of the karts. -->
<collision impulse-type="normal" <collision impulse-type="normal"
impulse="3000" impulse-time="0.1" terrain-impulse="160" impulse="3000" impulse-time="0.1" terrain-impulse="160"
restitution="1.0" bevel-factor="0.5 0.0 0.7" restitution="1.0" bevel-factor="0.5 0.0 0.3"
physical-wheel-position="-1" /> physical-wheel-position="0" />
<!-- Skidding: increase: multiplicative increase of skidding factor in each frame. <!-- Skidding: increase: multiplicative increase of skidding factor in each frame.
decrease: multiplicative decrease of skidding factor in each frame. decrease: multiplicative decrease of skidding factor in each frame.

View File

@ -12,24 +12,48 @@ if(MSVC OR APPLE)
"${CMAKE_CURRENT_BINARY_DIR}/../libpng/") "${CMAKE_CURRENT_BINARY_DIR}/../libpng/")
endif() endif()
if (SERVER_ONLY) if(NOT SERVER_ONLY)
add_definitions(-DNO_IRR_COMPILE_WITH_OPENGL_)
add_definitions(-DNO_IRR_COMPILE_WITH_X11_)
add_definitions(-DNO_IRR_COMPILE_WITH_WAYLAND_DEVICE_)
else()
if(NOT USE_GLES2) if(NOT USE_GLES2)
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR}) include_directories(${OPENGL_INCLUDE_DIR})
endif() endif()
endif()
if (UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
find_package(X11 REQUIRED) find_package(X11 REQUIRED)
include_directories(${X11_INCLUDE_DIR}) include_directories(${X11_INCLUDE_DIR})
endif()
if(ENABLE_WAYLAND_DEVICE) if(NOT X11_FOUND)
add_definitions(-D_IRR_COMPILE_WITH_WAYLAND_DEVICE_) message(FATAL_ERROR "X11 not found.")
endif()
if(NOT X11_Xrandr_FOUND)
message(FATAL_ERROR "XRANDR not found.")
endif()
endif()
if(ENABLE_WAYLAND_DEVICE)
find_package(Wayland REQUIRED)
include_directories(${WAYLAND_INCLUDE_DIR})
if(NOT WAYLAND_FOUND)
message(FATAL_ERROR "Wayland not found.")
endif()
add_definitions(-D_IRR_COMPILE_WITH_WAYLAND_DEVICE_)
endif()
if(USE_GLES2 OR ENABLE_WAYLAND_DEVICE)
find_package(EGL REQUIRED)
include_directories(${EGL_INCLUDE_DIR})
if(NOT EGL_FOUND)
message(FATAL_ERROR "EGL not found.")
endif()
endif()
else()
add_definitions(-DNO_IRR_COMPILE_WITH_OPENGL_)
add_definitions(-DNO_IRR_COMPILE_WITH_X11_)
add_definitions(-DNO_IRR_COMPILE_WITH_WAYLAND_DEVICE_)
endif() endif()
if(APPLE) if(APPLE)
@ -44,21 +68,18 @@ if(UNIX OR MINGW)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
endif() endif()
if(MSVC) if(WIN32)
add_definitions(/D_IRR_STATIC_LIB_) add_definitions(-D_IRR_STATIC_LIB_)
add_definitions(/D_CRT_SECURE_NO_WARNINGS) # Shut up about unsafe stuff add_definitions(-D_CRT_SECURE_NO_WARNINGS) # Shut up about unsafe stuff
elseif(MINGW)
add_definitions(-D_IRR_STATIC_LIB_)
add_definitions(-D_CRT_SECURE_NO_WARNINGS) # Shut up about unsafe stuff
else() else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pipe -O3 -fno-exceptions -fstrict-aliasing") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pipe -O3 -fno-exceptions -fstrict-aliasing")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pipe -O3 -fno-exceptions -fstrict-aliasing") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pipe -O3 -fno-exceptions -fstrict-aliasing")
if(CMAKE_COMPILER_IS_GNUCC) if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexpensive-optimizations") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexpensive-optimizations")
endif() endif()
if(CMAKE_COMPILER_IS_GNUCXX) if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexpensive-optimizations") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexpensive-optimizations")
endif() endif()
endif() endif()
if(USE_GLES2) if(USE_GLES2)
@ -559,16 +580,23 @@ if(APPLE)
endif() endif()
add_library(stkirrlicht STATIC ${IRRLICHT_SOURCES}) add_library(stkirrlicht STATIC ${IRRLICHT_SOURCES})
target_link_libraries(stkirrlicht ${PNG_LIBRARY} ${JPEG_LIBRARY} ${ZLIB_LIBRARY}) target_link_libraries(stkirrlicht ${PNG_LIBRARY} ${JPEG_LIBRARY} ${ZLIB_LIBRARY})
if(USE_GLES2 OR ENABLE_WAYLAND_DEVICE) if(NOT SERVER_ONLY)
target_link_libraries(stkirrlicht EGL) if(UNIX AND NOT APPLE)
endif() target_link_libraries(stkirrlicht ${X11_X11_LIB} ${X11_Xrandr_LIB})
endif()
if(ENABLE_WAYLAND_DEVICE) if(USE_GLES2 OR ENABLE_WAYLAND_DEVICE)
target_link_libraries(stkirrlicht wayland-client wayland-egl wayland-cursor xkbcommon) target_link_libraries(stkirrlicht ${EGL_LIBRARY})
endif()
if(ENABLE_WAYLAND_DEVICE)
target_link_libraries(stkirrlicht ${WAYLAND_LIBRARIES})
endif()
endif() endif()
if(WIN32) if(WIN32)
target_link_libraries(stkirrlicht imm32) target_link_libraries(stkirrlicht imm32 xinput9_1_0)
endif() endif()

View File

@ -177,8 +177,9 @@ namespace scene
\param newManager An optional new scene manager. \param newManager An optional new scene manager.
\return The newly created clone of this node. */ \return The newly created clone of this node. */
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) = 0; virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) = 0;
virtual void setFrameLoopOnce(s32 begin, s32 end) = 0;
virtual u32 getAnimationSetNum() = 0; virtual u32 getAnimationSetNum() = 0;
virtual s32 getAnimationSet() const = 0;
virtual void addAnimationSet(u32 start, u32 end) = 0; virtual void addAnimationSet(u32 start, u32 end) = 0;
virtual void useAnimationSet(u32 set_num) = 0; virtual void useAnimationSet(u32 set_num) = 0;
}; };

View File

@ -168,7 +168,7 @@ headers, e.g. Summer 2004. This is a Microsoft issue, not an Irrlicht one.
//! Define _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ if you want to use DirectInput for joystick handling. //! Define _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ if you want to use DirectInput for joystick handling.
/** This only applies to Windows devices, currently only supported under Win32 device. /** This only applies to Windows devices, currently only supported under Win32 device.
If not defined, Windows Multimedia library is used, which offers also broad support for joystick devices. */ If not defined, Windows Multimedia library is used, which offers also broad support for joystick devices. */
#undef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ #define _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_
#ifdef NO_IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ #ifdef NO_IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_
#undef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ #undef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_
#endif #endif

View File

@ -1002,5 +1002,60 @@ void CAnimatedMeshSceneNode::useAnimationSet(u32 set_num)
setFrameLoop(m_animation_set[set_num * 2], m_animation_set[set_num * 2 + 1]); setFrameLoop(m_animation_set[set_num * 2], m_animation_set[set_num * 2 + 1]);
} }
void CAnimatedMeshSceneNode::setFrameLoopOnce(s32 begin, s32 end)
{
if (LoopCallBack != NULL || !Looping)
{
return;
}
Looping = false;
class MiniLoopSetter : public IAnimationEndCallBack
{
private:
int m_old_start, m_old_end, m_new_start, m_new_end;
bool m_run_cb;
public:
MiniLoopSetter(int old_start, int old_end, int new_start, int new_end)
: m_old_start(old_start), m_old_end(old_end),
m_new_start(new_start), m_new_end(new_end), m_run_cb(false) {}
virtual void OnAnimationEnd(IAnimatedMeshSceneNode* node)
{
if (!m_run_cb)
{
m_run_cb = true;
node->setFrameLoop(m_new_start, m_new_end);
return;
}
if (m_run_cb)
{
node->setFrameLoop(m_old_start, m_old_end);
node->setLoopMode(true);
node->setAnimationEndCallback(NULL);
return;
}
}
};
MiniLoopSetter* mls = new MiniLoopSetter(StartFrame, EndFrame,
begin, end);
setAnimationEndCallback(mls);
mls->drop();
}
s32 CAnimatedMeshSceneNode::getAnimationSet() const
{
for (u32 i = 0; i < m_animation_set.size(); i += 2)
{
if (m_animation_set[i] == (u32)StartFrame &&
m_animation_set[i + 1] == (u32)EndFrame)
{
return (s32)(i >> 1);
}
}
return -1;
}
} // end namespace scene } // end namespace scene
} // end namespace irr } // end namespace irr

View File

@ -161,13 +161,14 @@ namespace scene
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
virtual u32 getAnimationSetNum() { return m_animation_set.size() / 2; } virtual u32 getAnimationSetNum() { return m_animation_set.size() / 2; }
virtual s32 getAnimationSet() const;
virtual void addAnimationSet(u32 start, u32 end) virtual void addAnimationSet(u32 start, u32 end)
{ {
m_animation_set.push_back(start); m_animation_set.push_back(start);
m_animation_set.push_back(end); m_animation_set.push_back(end);
} }
virtual void useAnimationSet(u32 set_num); virtual void useAnimationSet(u32 set_num);
virtual void setFrameLoopOnce(s32 begin, s32 end);
protected: protected:
//! Get a static mesh for the current frame of this animated mesh //! Get a static mesh for the current frame of this animated mesh

View File

@ -262,52 +262,75 @@ bool ContextManagerEGL::chooseConfig()
bool ContextManagerEGL::createSurface() bool ContextManagerEGL::createSurface()
{ {
if (m_creation_params.surface_type == CEGL_SURFACE_WINDOW) unsigned int colorspace_attr_pos = 0;
{ unsigned int largest_pbuffer_attr_pos = 0;
if (m_egl_surface == EGL_NO_SURFACE)
{
m_egl_surface = eglCreateWindowSurface(m_egl_display, m_egl_config,
m_egl_window, NULL);
}
if (m_egl_surface == EGL_NO_SURFACE) std::vector<EGLint> attribs;
if (m_creation_params.opengl_api == CEGL_API_OPENGL)
{
if (hasEGLExtension("EGL_KHR_gl_colorspace") || m_egl_version >= 150)
{ {
m_egl_surface = eglCreateWindowSurface(m_egl_display, m_egl_config, attribs.push_back(EGL_GL_COLORSPACE);
0, NULL); attribs.push_back(m_creation_params.handle_srgb ?
EGL_GL_COLORSPACE_SRGB : EGL_GL_COLORSPACE_LINEAR);
colorspace_attr_pos = attribs.size() - 1;
} }
} }
else if (m_creation_params.surface_type == CEGL_SURFACE_PBUFFER)
if (m_creation_params.surface_type == CEGL_SURFACE_PBUFFER)
{ {
if (m_egl_surface == EGL_NO_SURFACE) attribs.push_back(EGL_WIDTH);
{ attribs.push_back(m_creation_params.pbuffer_width);
std::vector<EGLint> pbuffer_attribs; attribs.push_back(EGL_HEIGHT);
pbuffer_attribs.push_back(EGL_WIDTH); attribs.push_back(m_creation_params.pbuffer_height);
pbuffer_attribs.push_back(m_creation_params.pbuffer_width); attribs.push_back(EGL_LARGEST_PBUFFER);
pbuffer_attribs.push_back(EGL_HEIGHT); attribs.push_back(EGL_FALSE);
pbuffer_attribs.push_back(m_creation_params.pbuffer_height); largest_pbuffer_attr_pos = attribs.size() - 1;
pbuffer_attribs.push_back(EGL_NONE); }
pbuffer_attribs.push_back(0);
m_egl_surface = eglCreatePbufferSurface(m_egl_display, attribs.push_back(EGL_NONE);
m_egl_config, attribs.push_back(0);
&pbuffer_attribs[0]);
if (m_egl_surface == EGL_NO_SURFACE)
{
if (m_creation_params.surface_type == CEGL_SURFACE_WINDOW)
{
m_egl_surface = eglCreateWindowSurface(m_egl_display, m_egl_config,
m_egl_window, &attribs[0]);
} }
else if (m_creation_params.surface_type == CEGL_SURFACE_PBUFFER)
if (m_egl_surface == EGL_NO_SURFACE)
{ {
std::vector<EGLint> pbuffer_attribs; m_egl_surface = eglCreatePbufferSurface(m_egl_display, m_egl_config,
pbuffer_attribs.push_back(EGL_WIDTH); &attribs[0]);
pbuffer_attribs.push_back(m_creation_params.pbuffer_width); }
pbuffer_attribs.push_back(EGL_HEIGHT); }
pbuffer_attribs.push_back(m_creation_params.pbuffer_height);
pbuffer_attribs.push_back(EGL_LARGEST_PBUFFER);
pbuffer_attribs.push_back(EGL_TRUE);
pbuffer_attribs.push_back(EGL_NONE);
pbuffer_attribs.push_back(0);
m_egl_surface = eglCreatePbufferSurface(m_egl_display, if (m_egl_surface == EGL_NO_SURFACE && colorspace_attr_pos > 0 &&
m_egl_config, m_creation_params.handle_srgb == true)
&pbuffer_attribs[0]); {
attribs[colorspace_attr_pos] = EGL_GL_COLORSPACE_LINEAR;
if (m_creation_params.surface_type == CEGL_SURFACE_WINDOW)
{
m_egl_surface = eglCreateWindowSurface(m_egl_display, m_egl_config,
m_egl_window, &attribs[0]);
}
else if (m_creation_params.surface_type == CEGL_SURFACE_PBUFFER)
{
m_egl_surface = eglCreatePbufferSurface(m_egl_display, m_egl_config,
&attribs[0]);
}
}
if (m_egl_surface == EGL_NO_SURFACE && largest_pbuffer_attr_pos > 0)
{
attribs[largest_pbuffer_attr_pos] = EGL_TRUE;
if (m_creation_params.surface_type == CEGL_SURFACE_PBUFFER)
{
m_egl_surface = eglCreatePbufferSurface(m_egl_display, m_egl_config,
&attribs[0]);
} }
} }

View File

@ -30,6 +30,15 @@
#ifndef EGL_CONTEXT_MINOR_VERSION #ifndef EGL_CONTEXT_MINOR_VERSION
#define EGL_CONTEXT_MINOR_VERSION 0x30FB #define EGL_CONTEXT_MINOR_VERSION 0x30FB
#endif #endif
#ifndef EGL_GL_COLORSPACE
#define EGL_GL_COLORSPACE 0x309D
#endif
#ifndef EGL_GL_COLORSPACE_SRGB
#define EGL_GL_COLORSPACE_SRGB 0x3089
#endif
#ifndef EGL_GL_COLORSPACE_LINEAR
#define EGL_GL_COLORSPACE_LINEAR 0x308A
#endif
enum ContextEGLOpenGLAPI enum ContextEGLOpenGLAPI
{ {
@ -50,6 +59,7 @@ struct ContextEGLParams
EGLNativeWindowType window; EGLNativeWindowType window;
EGLNativeDisplayType display; EGLNativeDisplayType display;
bool force_legacy_device; bool force_legacy_device;
bool handle_srgb;
bool with_alpha_channel; bool with_alpha_channel;
bool vsync_enabled; bool vsync_enabled;
int pbuffer_width; int pbuffer_width;

View File

@ -673,11 +673,15 @@ bool CIrrDeviceLinux::createWindow()
#elif defined(GLX_SGIS_multisample) #elif defined(GLX_SGIS_multisample)
GLX_SAMPLE_BUFFERS_SGIS, 1, GLX_SAMPLE_BUFFERS_SGIS, 1,
GLX_SAMPLES_SGIS, CreationParams.AntiAlias, // 18,19 GLX_SAMPLES_SGIS, CreationParams.AntiAlias, // 18,19
#else
#error
#endif #endif
#ifdef GLX_ARB_framebuffer_sRGB #ifdef GLX_ARB_framebuffer_sRGB
GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, CreationParams.HandleSRGB, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, CreationParams.HandleSRGB,
#elif defined(GLX_EXT_framebuffer_sRGB) #elif defined(GLX_EXT_framebuffer_sRGB)
GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, CreationParams.HandleSRGB, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, CreationParams.HandleSRGB,
#else
#error
#endif #endif
GLX_STEREO, CreationParams.Stereobuffer?True:False, GLX_STEREO, CreationParams.Stereobuffer?True:False,
None None
@ -719,6 +723,39 @@ bool CIrrDeviceLinux::createWindow()
} }
} }
} }
// Try to disable sRGB framebuffer
if (!configList && CreationParams.HandleSRGB)
{
os::Printer::log("No sRGB framebuffer available.", ELL_WARNING);
CreationParams.HandleSRGB=false;
visualAttrBuffer[21] = GLX_DONT_CARE;
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
if (!configList && CreationParams.AntiAlias)
{
while (!configList && (visualAttrBuffer[19]>1))
{
visualAttrBuffer[19] -= 1;
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
}
if (!configList)
{
visualAttrBuffer[17] = 0;
visualAttrBuffer[19] = 0;
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
if (configList)
{
os::Printer::log("No FSAA available.", ELL_WARNING);
CreationParams.AntiAlias=0;
}
else
{
//reenable multisampling
visualAttrBuffer[17] = 1;
visualAttrBuffer[19] = CreationParams.AntiAlias;
}
}
}
}
// Next try with flipped stencil buffer value // Next try with flipped stencil buffer value
// If the first round was with stencil flag it's now without // If the first round was with stencil flag it's now without
// Other way round also makes sense because some configs // Other way round also makes sense because some configs
@ -1218,6 +1255,9 @@ bool CIrrDeviceLinux::createInputContext()
return false; return false;
} }
// It's showed as memory leak, but we shouldn't delete it. From the xlib
// documentation: "The returned modifiers string is owned by Xlib and
// should not be modified or freed by the client."
char* p = XSetLocaleModifiers(""); char* p = XSetLocaleModifiers("");
if (p == NULL) if (p == NULL)
{ {

View File

@ -537,6 +537,7 @@ public:
device->m_seat = static_cast<wl_seat*>(wl_registry_bind(registry, device->m_seat = static_cast<wl_seat*>(wl_registry_bind(registry,
name, &wl_seat_interface, name, &wl_seat_interface,
version < 4 ? version : 4)); version < 4 ? version : 4));
wl_seat_add_listener(device->m_seat, &seat_listener, device);
} }
else if (interface_str == "wl_shm") else if (interface_str == "wl_shm")
{ {
@ -547,6 +548,7 @@ public:
{ {
device->m_output = static_cast<wl_output*>(wl_registry_bind(registry, device->m_output = static_cast<wl_output*>(wl_registry_bind(registry,
name, &wl_output_interface, 2)); name, &wl_output_interface, 2));
wl_output_add_listener(device->m_output, &output_listener, device);
} }
} }
@ -700,9 +702,6 @@ CIrrDeviceWayland::CIrrDeviceWayland(const SIrrlichtCreationParameters& params)
return; return;
} }
wl_seat_add_listener(m_seat, &WaylandCallbacks::seat_listener, this);
wl_output_add_listener(m_output, &WaylandCallbacks::output_listener, this);
createDriver(); createDriver();
if (VideoDriver) if (VideoDriver)
@ -716,6 +715,9 @@ CIrrDeviceWayland::~CIrrDeviceWayland()
{ {
delete m_egl_context; delete m_egl_context;
if (m_egl_window)
wl_egl_window_destroy(m_egl_window);
if (m_keyboard) if (m_keyboard)
wl_keyboard_destroy(m_keyboard); wl_keyboard_destroy(m_keyboard);
@ -731,14 +733,45 @@ CIrrDeviceWayland::~CIrrDeviceWayland()
if (m_shell_surface) if (m_shell_surface)
wl_shell_surface_destroy(m_shell_surface); wl_shell_surface_destroy(m_shell_surface);
wl_output_destroy(m_output); if (m_surface)
wl_seat_destroy(m_seat); wl_surface_destroy(m_surface);
wl_registry_destroy(m_registry);
if (m_shell)
wl_shell_destroy(m_shell);
if (m_shm)
wl_shm_destroy(m_shm);
if (m_compositor)
wl_compositor_destroy(m_compositor);
if (m_output)
wl_output_destroy(m_output);
if (m_seat)
wl_seat_destroy(m_seat);
if (m_registry)
wl_registry_destroy(m_registry);
if (m_xkb_state)
xkb_state_unref(m_xkb_state);
if (m_xkb_keymap)
xkb_keymap_unref(m_xkb_keymap);
if (m_xkb_compose_state)
xkb_compose_state_unref(m_xkb_compose_state);
if (m_xkb_compose_table)
xkb_compose_table_unref(m_xkb_compose_table);
if (m_xkb_context)
xkb_context_unref(m_xkb_context);
wl_display_flush(m_display); wl_display_flush(m_display);
wl_display_disconnect(m_display); wl_display_disconnect(m_display);
xkb_context_unref(m_xkb_context);
closeJoysticks(); closeJoysticks();
} }
@ -761,6 +794,7 @@ bool CIrrDeviceWayland::initEGL()
egl_params.surface_type = CEGL_SURFACE_WINDOW; egl_params.surface_type = CEGL_SURFACE_WINDOW;
egl_params.force_legacy_device = CreationParams.ForceLegacyDevice; egl_params.force_legacy_device = CreationParams.ForceLegacyDevice;
egl_params.handle_srgb = CreationParams.HandleSRGB;
egl_params.with_alpha_channel = CreationParams.WithAlphaChannel; egl_params.with_alpha_channel = CreationParams.WithAlphaChannel;
egl_params.vsync_enabled = CreationParams.Vsync; egl_params.vsync_enabled = CreationParams.Vsync;
egl_params.window = m_egl_window; egl_params.window = m_egl_window;

File diff suppressed because it is too large Load Diff

View File

@ -69,6 +69,7 @@ namespace video
ContextEGLParams egl_params; ContextEGLParams egl_params;
egl_params.opengl_api = CEGL_API_OPENGL_ES; egl_params.opengl_api = CEGL_API_OPENGL_ES;
egl_params.surface_type = CEGL_SURFACE_WINDOW; egl_params.surface_type = CEGL_SURFACE_WINDOW;
egl_params.handle_srgb = Params.HandleSRGB;
egl_params.force_legacy_device = Params.ForceLegacyDevice; egl_params.force_legacy_device = Params.ForceLegacyDevice;
egl_params.with_alpha_channel = Params.WithAlphaChannel; egl_params.with_alpha_channel = Params.WithAlphaChannel;
egl_params.vsync_enabled = Params.Vsync; egl_params.vsync_enabled = Params.Vsync;
@ -433,6 +434,13 @@ namespace video
addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_ONETEXTURE_BLEND, this)); addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_ONETEXTURE_BLEND, this));
delete[] FPVSData;
delete[] FPFSData;
delete[] NMVSData;
delete[] NMFSData;
delete[] PMVSData;
delete[] PMFSData;
// Create 2D material renderer. // Create 2D material renderer.
core::stringc R2DVSPath = shaders_path; core::stringc R2DVSPath = shaders_path;
@ -476,6 +484,9 @@ namespace video
R2DFSFile->drop(); R2DFSFile->drop();
MaterialRenderer2D = new COGLES2Renderer2D(R2DVSData, R2DFSData, this); MaterialRenderer2D = new COGLES2Renderer2D(R2DVSData, R2DFSData, this);
delete[] R2DVSData;
delete[] R2DFSData;
} }

View File

@ -93,7 +93,7 @@ COGLES2MaterialRenderer::~COGLES2MaterialRenderer()
if (Program) if (Program)
{ {
GLuint shaders[8]; GLuint shaders[8];
GLint count; GLint count = 0;
glGetAttachedShaders(Program, 8, &count, shaders); glGetAttachedShaders(Program, 8, &count, shaders);
count=core::min_(count,8); count=core::min_(count,8);

View File

@ -809,7 +809,7 @@ bool COpenGLDriver::genericDriverInit()
u32 i; u32 i;
CurrentTexture.clear(); CurrentTexture.clear();
// load extensions // load extensions
initExtensions(Params.Stencilbuffer); initExtensions(Params.Stencilbuffer, useCoreContext);
if (queryFeature(EVDF_ARB_GLSL)) if (queryFeature(EVDF_ARB_GLSL))
{ {
char buf[32]; char buf[32];
@ -872,9 +872,11 @@ bool COpenGLDriver::genericDriverInit()
glClearDepth(1.0); glClearDepth(1.0);
if (!useCoreContext) if (!useCoreContext)
{
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
}
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_LEQUAL);
glFrontFace(GL_CW); glFrontFace(GL_CW);
// adjust flat coloring scheme to DirectX version // adjust flat coloring scheme to DirectX version

View File

@ -327,7 +327,7 @@ void COpenGLExtensionHandler::dumpFramebufferFormats() const
} }
void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) void COpenGLExtensionHandler::initExtensions(bool stencilBuffer, bool useCoreContext)
{ {
const f32 ogl_ver = core::fast_atof(reinterpret_cast<const c8*>(glGetString(GL_VERSION))); const f32 ogl_ver = core::fast_atof(reinterpret_cast<const c8*>(glGetString(GL_VERSION)));
Version = static_cast<u16>(core::floor32(ogl_ver)*100+core::round32(core::fract(ogl_ver)*10.0f)); Version = static_cast<u16>(core::floor32(ogl_ver)*100+core::round32(core::fract(ogl_ver)*10.0f));
@ -337,9 +337,15 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer)
os::Printer::log("OpenGL driver version is not 1.2 or better.", ELL_WARNING); os::Printer::log("OpenGL driver version is not 1.2 or better.", ELL_WARNING);
{ {
const char* t = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); const char* t = NULL;
size_t len = 0; size_t len = 0;
c8 *str = 0; c8 *str = 0;
if (!useCoreContext)
{
t = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
}
if (t) if (t)
{ {
len = strlen(t); len = strlen(t);

View File

@ -924,7 +924,7 @@ class COpenGLExtensionHandler
COpenGLExtensionHandler(); COpenGLExtensionHandler();
// deferred initialization // deferred initialization
void initExtensions(bool stencilBuffer); void initExtensions(bool stencilBuffer, bool useCoreContext);
//! queries the features of the driver, returns true if feature is available //! queries the features of the driver, returns true if feature is available
bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const; bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const;

View File

@ -77,7 +77,10 @@ IMesh* CSkinnedMesh::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32
{ {
const bool is_hw_skinning_before = HardwareSkinning; const bool is_hw_skinning_before = HardwareSkinning;
if (is_hw_skinning_before) if (is_hw_skinning_before)
{
HardwareSkinning = false; HardwareSkinning = false;
LastAnimatedFrame = -1;
}
//animate(frame,startFrameLoop, endFrameLoop); //animate(frame,startFrameLoop, endFrameLoop);
if (frame==-1) if (frame==-1)
return this; return this;

View File

@ -1,5 +1,6 @@
# Modify this file to change the last-modified date when you add/remove a file. # Modify this file to change the last-modified date when you add/remove a file.
# This will then trigger a new cmake run automatically. # This will then trigger a new cmake run automatically.
# This will then trigger a new cmake run automatically.
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp") file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp") file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*") file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")

View File

@ -73,7 +73,8 @@ ThreeDAnimation::~ThreeDAnimation()
*/ */
void ThreeDAnimation::update(float dt) void ThreeDAnimation::update(float dt)
{ {
//if ( UserConfigParams::m_graphical_effects || m_important_animation ) //if (UserConfigParams::m_graphical_effects > 1 ||
// (UserConfigParams::m_graphical_effects > 0 && m_important_animation))
{ {
Vec3 xyz = m_object->getPosition(); Vec3 xyz = m_object->getPosition();
Vec3 scale = m_object->getScale(); Vec3 scale = m_object->getScale();

View File

@ -47,9 +47,9 @@ public:
virtual void reallySetSpeedPosition(float f, virtual void reallySetSpeedPosition(float f,
const Vec3 &p) {} const Vec3 &p) {}
virtual void play() {} virtual void play() {}
virtual void reallyPlayNow() {} virtual void reallyPlayNow(SFXBuffer* buffer = NULL) {}
virtual void play(const Vec3 &xyz) {} virtual void play(const Vec3 &xyz, SFXBuffer* buffer = NULL) {}
virtual void reallyPlayNow(const Vec3 &xyz) {} virtual void reallyPlayNow(const Vec3 &xyz, SFXBuffer* buffer = NULL) {}
virtual void stop() {} virtual void stop() {}
virtual void reallyStopNow() {} virtual void reallyStopNow() {}
virtual void pause() {} virtual void pause() {}

View File

@ -145,10 +145,23 @@ void MusicInformation::startMusic()
m_time_since_faster = 0.0f; m_time_since_faster = 0.0f;
m_mode = SOUND_NORMAL; m_mode = SOUND_NORMAL;
if (m_normal_filename== "") return; if (m_normal_music)
{
delete m_normal_music;
m_normal_music = NULL;
}
if (m_fast_music)
{
delete m_fast_music;
m_fast_music = NULL;
}
// First load the 'normal' music // First load the 'normal' music
// ----------------------------- // -----------------------------
if (m_normal_filename.empty())
return;
if (StringUtils::getExtension(m_normal_filename) != "ogg") if (StringUtils::getExtension(m_normal_filename) != "ogg")
{ {
Log::warn("MusicInformation", "Music file %s is not found or file " Log::warn("MusicInformation", "Music file %s is not found or file "
@ -156,15 +169,13 @@ void MusicInformation::startMusic()
return; return;
} }
if (m_normal_music) delete m_normal_music;
#if HAVE_OGGVORBIS #if HAVE_OGGVORBIS
m_normal_music = new MusicOggStream(m_normal_loop_start); m_normal_music = new MusicOggStream(m_normal_loop_start);
#else #else
m_normal_music = new MusicDummy(); m_normal_music = new MusicDummy();
#endif #endif
if((m_normal_music->load(m_normal_filename)) == false) if (m_normal_music->load(m_normal_filename) == false)
{ {
delete m_normal_music; delete m_normal_music;
m_normal_music = NULL; m_normal_music = NULL;
@ -178,18 +189,14 @@ void MusicInformation::startMusic()
// Then (if available) load the music for the last track // Then (if available) load the music for the last track
// ----------------------------------------------------- // -----------------------------------------------------
if (m_fast_music) delete m_fast_music; if (m_fast_filename.empty())
if (m_fast_filename == "") return;
{
m_fast_music = NULL;
return; // no fast music
}
if(StringUtils::getExtension(m_fast_filename)!="ogg") if (StringUtils::getExtension(m_fast_filename) != "ogg")
{ {
Log::warn( Log::warn("MusicInformation",
"Music file %s format not recognized, fast music is ignored", "Music file %s format not recognized, fast music is ignored",
m_fast_filename.c_str()); m_fast_filename.c_str());
return; return;
} }
@ -199,10 +206,10 @@ void MusicInformation::startMusic()
m_fast_music = new MusicDummy(); m_fast_music = new MusicDummy();
#endif #endif
if((m_fast_music->load(m_fast_filename)) == false) if (m_fast_music->load(m_fast_filename) == false)
{ {
delete m_fast_music; delete m_fast_music;
m_fast_music=0; m_fast_music = NULL;
Log::warn("MusicInformation", "Unabled to load fast music %s, not " Log::warn("MusicInformation", "Unabled to load fast music %s, not "
"supported or not found.\n", m_fast_filename.c_str()); "supported or not found.\n", m_fast_filename.c_str());
return; return;

View File

@ -64,9 +64,9 @@ public:
virtual void setLoop(bool status) = 0; virtual void setLoop(bool status) = 0;
virtual void reallySetLoop(bool status) = 0; virtual void reallySetLoop(bool status) = 0;
virtual void play() = 0; virtual void play() = 0;
virtual void reallyPlayNow() = 0; virtual void reallyPlayNow(SFXBuffer* buffer = NULL) = 0;
virtual void play(const Vec3 &xyz) = 0; virtual void play(const Vec3 &xyz, SFXBuffer* buffer = NULL) = 0;
virtual void reallyPlayNow(const Vec3 &xyz) = 0; virtual void reallyPlayNow(const Vec3 &xyz, SFXBuffer* buffer = NULL) = 0;
virtual void stop() = 0; virtual void stop() = 0;
virtual void reallyStopNow() = 0; virtual void reallyStopNow() = 0;
virtual void pause() = 0; virtual void pause() = 0;

View File

@ -217,6 +217,15 @@ void SFXManager::queue(SFXCommands command, SFXBase *sfx, const Vec3 &p)
queueCommand(sfx_command); queueCommand(sfx_command);
} // queue (Vec3) } // queue (Vec3)
//----------------------------------------------------------------------------
void SFXManager::queue(SFXCommands command, SFXBase *sfx, const Vec3 &p, SFXBuffer* buffer)
{
SFXCommand *sfx_command = new SFXCommand(command, sfx, p);
sfx_command->m_buffer = buffer;
queueCommand(sfx_command);
} // queue (Vec3)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Adds a sound effect command with a float and a Vec3 parameter to the queue /** Adds a sound effect command with a float and a Vec3 parameter to the queue
* of the sfx manager. Openal commands can sometimes cause a 5ms delay, so it * of the sfx manager. Openal commands can sometimes cause a 5ms delay, so it
@ -340,7 +349,7 @@ void* SFXManager::mainLoop(void *obj)
{ {
case SFX_PLAY: current->m_sfx->reallyPlayNow(); break; case SFX_PLAY: current->m_sfx->reallyPlayNow(); break;
case SFX_PLAY_POSITION: case SFX_PLAY_POSITION:
current->m_sfx->reallyPlayNow(current->m_parameter); break; current->m_sfx->reallyPlayNow(current->m_parameter, current->m_buffer); break;
case SFX_STOP: current->m_sfx->reallyStopNow(); break; case SFX_STOP: current->m_sfx->reallyStopNow(); break;
case SFX_PAUSE: current->m_sfx->reallyPauseNow(); break; case SFX_PAUSE: current->m_sfx->reallyPauseNow(); break;
case SFX_RESUME: current->m_sfx->reallyResumeNow(); break; case SFX_RESUME: current->m_sfx->reallyResumeNow(); break;
@ -675,6 +684,22 @@ SFXBase* SFXManager::createSoundSource(const std::string &name,
return createSoundSource( i->second, add_to_SFXList ); return createSoundSource( i->second, add_to_SFXList );
} // createSoundSource } // createSoundSource
//----------------------------------------------------------------------------
SFXBuffer* SFXManager::getBuffer(const std::string &name)
{
std::map<std::string, SFXBuffer*>::iterator i = m_all_sfx_types.find(name);
if (i == m_all_sfx_types.end())
{
Log::error("SFXManager",
"SFXManager::getBuffer could not find the "
"requested sound effect : '%s'.", name.c_str());
return NULL;
}
return i->second;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Returns true if a sfx with the given name exists. /** Returns true if a sfx with the given name exists.
* \param name The internal name of the sfx (not the name of the ogg file) * \param name The internal name of the sfx (not the name of the ogg file)

View File

@ -122,6 +122,9 @@ private:
/** The sound effect for which the command should be executed. */ /** The sound effect for which the command should be executed. */
SFXBase *m_sfx; SFXBase *m_sfx;
/** The sound buffer to play (null = no change) */
SFXBuffer *m_buffer = NULL;
/** Stores music information for music commands. */ /** Stores music information for music commands. */
MusicInformation *m_music_information; MusicInformation *m_music_information;
@ -232,12 +235,14 @@ private:
public: public:
static void create(); static void create();
static void destroy(); static void destroy();
void queue(SFXCommands command, SFXBase *sfx=NULL); void queue(SFXCommands command, SFXBase *sfx=NULL);
void queue(SFXCommands command, SFXBase *sfx, float f); void queue(SFXCommands command, SFXBase *sfx, float f);
void queue(SFXCommands command, SFXBase *sfx, const Vec3 &p); void queue(SFXCommands command, SFXBase *sfx, const Vec3 &p);
void queue(SFXCommands command, SFXBase *sfx, float f, const Vec3 &p); void queue(SFXCommands command, SFXBase *sfx, float f, const Vec3 &p);
void queue(SFXCommands command, MusicInformation *mi); void queue(SFXCommands command, MusicInformation *mi);
void queue(SFXCommands command, MusicInformation *mi, float f); void queue(SFXCommands command, MusicInformation *mi, float f);
void queue(SFXCommands command, SFXBase *sfx, const Vec3 &p, SFXBuffer* buffer);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Static function to get the singleton sfx manager. */ /** Static function to get the singleton sfx manager. */
static SFXManager *get() static SFXManager *get()
@ -296,6 +301,9 @@ public:
/** Returns the current position of the listener. */ /** Returns the current position of the listener. */
Vec3 getListenerPos() const { return m_listener_position.getData(); } Vec3 getListenerPos() const { return m_listener_position.getData(); }
// ------------------------------------------------------------------------
SFXBuffer* getBuffer(const std::string &name);
}; };
#endif // HEADER_SFX_MANAGER_HPP #endif // HEADER_SFX_MANAGER_HPP

View File

@ -70,6 +70,7 @@ SFXOpenAL::~SFXOpenAL()
if (m_status!=SFX_UNKNOWN && m_status!=SFX_NOT_INITIALISED) if (m_status!=SFX_UNKNOWN && m_status!=SFX_NOT_INITIALISED)
{ {
alDeleteSources(1, &m_sound_source); alDeleteSources(1, &m_sound_source);
SFXManager::checkError("deleting a source");
} }
if (m_owns_buffer && m_sound_buffer) if (m_owns_buffer && m_sound_buffer)
@ -364,7 +365,7 @@ void SFXOpenAL::play()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Plays this sound effect. /** Plays this sound effect.
*/ */
void SFXOpenAL::reallyPlayNow() void SFXOpenAL::reallyPlayNow(SFXBuffer* buffer)
{ {
if (!SFXManager::get()->sfxAllowed()) return; if (!SFXManager::get()->sfxAllowed()) return;
if (m_status==SFX_NOT_INITIALISED) if (m_status==SFX_NOT_INITIALISED)
@ -376,6 +377,18 @@ void SFXOpenAL::reallyPlayNow()
if (m_status==SFX_UNKNOWN) return; if (m_status==SFX_UNKNOWN) return;
} }
if (buffer != NULL)
{
if (m_status == SFX_PLAYING || m_status == SFX_PAUSED)
reallyStopNow();
m_sound_buffer = buffer;
alSourcei(m_sound_source, AL_BUFFER, m_sound_buffer->getBufferID());
if (!SFXManager::checkError("attaching the buffer to the source"))
return;
}
alSourcePlay(m_sound_source); alSourcePlay(m_sound_source);
SFXManager::checkError("playing"); SFXManager::checkError("playing");
// Esp. with terrain sounds it can (very likely) happen that the status // Esp. with terrain sounds it can (very likely) happen that the status
@ -391,8 +404,11 @@ void SFXOpenAL::reallyPlayNow()
/** This actually queues up the sfx in the sfx manager. It will be started /** This actually queues up the sfx in the sfx manager. It will be started
* from a separate thread later (in this frame). * from a separate thread later (in this frame).
*/ */
void SFXOpenAL::play(const Vec3 &position) void SFXOpenAL::play(const Vec3 &position, SFXBuffer* buffer)
{ {
if (m_owns_buffer && buffer != NULL)
assert(false); // sources that own a buffer cannot play any other buffer
if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return; if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
if(m_status==SFX_STOPPED || m_status==SFX_NOT_INITIALISED) if(m_status==SFX_STOPPED || m_status==SFX_NOT_INITIALISED)
@ -404,16 +420,15 @@ void SFXOpenAL::play(const Vec3 &position)
// - which can happen if the sfx thread had no time to actually start // - which can happen if the sfx thread had no time to actually start
// it yet. // it yet.
m_status = SFX_PLAYING; m_status = SFX_PLAYING;
SFXManager::get()->queue(SFXManager::SFX_PLAY_POSITION, this, position); SFXManager::get()->queue(SFXManager::SFX_PLAY_POSITION, this, position, buffer);
} // play(Vec3) } // play(Vec3)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Plays this sound effect. /** Plays this sound effect.
*/ */
void SFXOpenAL::reallyPlayNow(const Vec3 &position) void SFXOpenAL::reallyPlayNow(const Vec3 &position, SFXBuffer* buffer)
{ {
reallySetPosition(position); reallySetPosition(position);
reallyPlayNow(); reallyPlayNow(buffer);
} // reallyPlayNow(Vec3) } // reallyPlayNow(Vec3)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -527,4 +542,6 @@ void SFXOpenAL::setRolloff(float rolloff)
alSourcef (m_sound_source, AL_ROLLOFF_FACTOR, rolloff); alSourcef (m_sound_source, AL_ROLLOFF_FACTOR, rolloff);
} }
//-----------------------------------------------------------------------------
#endif //if HAVE_OGGVORBIS #endif //if HAVE_OGGVORBIS

View File

@ -29,6 +29,7 @@
#endif #endif
#include "audio/sfx_base.hpp" #include "audio/sfx_base.hpp"
#include "utils/leak_check.hpp" #include "utils/leak_check.hpp"
#include "utils/cpp2011.hpp"
/** /**
* \brief OpenAL implementation of the abstract SFXBase interface * \brief OpenAL implementation of the abstract SFXBase interface
@ -81,11 +82,11 @@ public:
virtual ~SFXOpenAL(); virtual ~SFXOpenAL();
virtual void updatePlayingSFX(float dt); virtual void updatePlayingSFX(float dt);
virtual bool init(); virtual bool init() OVERRIDE;
virtual void play(); virtual void play() OVERRIDE;
virtual void reallyPlayNow(); virtual void reallyPlayNow(SFXBuffer* buffer = NULL) OVERRIDE;
virtual void play(const Vec3 &xyz); virtual void play(const Vec3 &xyz, SFXBuffer* buffer = NULL) OVERRIDE;
virtual void reallyPlayNow(const Vec3 &xyz); virtual void reallyPlayNow(const Vec3 &xyz, SFXBuffer* buffer = NULL) OVERRIDE;
virtual void setLoop(bool status); virtual void setLoop(bool status);
virtual void reallySetLoop(bool status); virtual void reallySetLoop(bool status);
virtual void stop(); virtual void stop();

View File

@ -431,13 +431,18 @@ namespace UserConfigParams
"considered as centered in steering button.")); "considered as centered in steering button."));
PARAM_PREFIX FloatUserConfigParam m_multitouch_deadzone_edge PARAM_PREFIX FloatUserConfigParam m_multitouch_deadzone_edge
PARAM_DEFAULT( FloatUserConfigParam(0.25f, "multitouch_deadzone_edge", PARAM_DEFAULT( FloatUserConfigParam(0.1f, "multitouch_deadzone_edge",
&m_multitouch_group, &m_multitouch_group,
"A parameter in range [0, 0.5] that determines the zone that is " "A parameter in range [0, 0.5] that determines the zone that is "
"considered as max value in steering button.")); "considered as max value in steering button."));
PARAM_PREFIX FloatUserConfigParam m_multitouch_tilt_factor
PARAM_DEFAULT( FloatUserConfigParam(4.0f, "multitouch_tilt_factor",
&m_multitouch_group,
"A parameter that determines general accelerometer sensitivity."));
PARAM_PREFIX FloatUserConfigParam m_multitouch_scale PARAM_PREFIX FloatUserConfigParam m_multitouch_scale
PARAM_DEFAULT( FloatUserConfigParam(1.0f, "multitouch_scale", PARAM_DEFAULT( FloatUserConfigParam(1.1f, "multitouch_scale",
&m_multitouch_group, &m_multitouch_group,
"A parameter in range [0.5, 1.5] that determines the scale of the " "A parameter in range [0.5, 1.5] that determines the scale of the "
"multitouch interface.")); "multitouch interface."));
@ -722,9 +727,9 @@ namespace UserConfigParams
#define FBO_DEFAULT true #define FBO_DEFAULT true
#endif #endif
PARAM_PREFIX BoolUserConfigParam m_graphical_effects PARAM_PREFIX IntUserConfigParam m_graphical_effects
PARAM_DEFAULT( BoolUserConfigParam(true, "anim_gfx", PARAM_DEFAULT( IntUserConfigParam(2, "anim_gfx",
&m_graphics_quality, "Scenery animations") ); &m_graphics_quality, "Scenery animations: 0 disabled, 1 only important, 2 enabled") );
// This saves the actual user preference. // This saves the actual user preference.
PARAM_PREFIX IntUserConfigParam m_xmas_mode PARAM_PREFIX IntUserConfigParam m_xmas_mode

View File

@ -23,6 +23,7 @@
#include "karts/abstract_kart.hpp" #include "karts/abstract_kart.hpp"
#include "karts/explosion_animation.hpp" #include "karts/explosion_animation.hpp"
#include "karts/kart.hpp" #include "karts/kart.hpp"
#include "karts/kart_model.hpp"
#include "karts/kart_properties.hpp" #include "karts/kart_properties.hpp"
#include "karts/skidding.hpp" #include "karts/skidding.hpp"
#include "physics/btKart.hpp" #include "physics/btKart.hpp"
@ -92,9 +93,7 @@ void CameraDebug::update(float dt)
{ {
Camera::update(dt); Camera::update(dt);
// To view inside tunnels in top mode, increase near value m_camera->setNearValue(1.0f);
m_camera->setNearValue(m_default_debug_Type==CM_DEBUG_TOP_OF_KART
? 27.0f : 1.0f);
float above_kart, cam_angle, side_way, distance; float above_kart, cam_angle, side_way, distance;
@ -104,8 +103,17 @@ void CameraDebug::update(float dt)
{ {
core::vector3df xyz = m_kart->getXYZ().toIrrVector(); core::vector3df xyz = m_kart->getXYZ().toIrrVector();
m_camera->setTarget(xyz); m_camera->setTarget(xyz);
#define CLOSE_TO_KART
#ifdef CLOSE_TO_KART
// Better for debugging physics/collision issues
xyz.Y = xyz.Y+7;
m_camera->setNearValue(7.0f);
#else
// Very high few, better for debugging AI behaviour
xyz.Y = xyz.Y+55; xyz.Y = xyz.Y+55;
xyz.Z -= 5.0f; xyz.Z -= 5.0f;
m_camera->setNearValue(27.0f);
#endif
m_camera->setPosition(xyz); m_camera->setPosition(xyz);
} }
else if (m_default_debug_Type==CM_DEBUG_SIDE_OF_KART) else if (m_default_debug_Type==CM_DEBUG_SIDE_OF_KART)

View File

@ -253,6 +253,13 @@ void CentralVideoSettings::init()
hasExplicitAttribLocation = true; hasExplicitAttribLocation = true;
} }
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_UNIFORM_BUFFER_OBJECT) &&
m_glsl == true)
{
hasUBO = true;
Log::info("GLDriver", "ARB Uniform Buffer Object Present");
}
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_TEXTURE_FORMAT_BGRA8888) && if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_TEXTURE_FORMAT_BGRA8888) &&
(hasGLExtension("GL_IMG_texture_format_BGRA8888") || (hasGLExtension("GL_IMG_texture_format_BGRA8888") ||
hasGLExtension("GL_EXT_texture_format_BGRA8888"))) hasGLExtension("GL_EXT_texture_format_BGRA8888")))

View File

@ -80,26 +80,6 @@ void InstanceFiller<GlowInstanceData>::add(GLMesh* mesh,
instance.Color = nd->getGlowColor().color; instance.Color = nd->getGlowColor().color;
} }
// ----------------------------------------------------------------------------
template<>
void expandTexSecondPass<GrassMat>(const GLMesh &mesh,
const std::vector<GLuint> &prefilled_tex)
{
TexExpander<typename GrassMat::InstancedSecondPassShader>::
expandTex(mesh, GrassMat::SecondPassTextures, prefilled_tex[0],
prefilled_tex[1], prefilled_tex[2], prefilled_tex[3]);
}
// ----------------------------------------------------------------------------
template<>
void expandHandlesSecondPass<GrassMat>(const std::vector<uint64_t> &handles)
{
uint64_t nulltex[10] = {};
HandleExpander<GrassMat::InstancedSecondPassShader>::
expand(nulltex, GrassMat::SecondPassTextures,
handles[0], handles[1], handles[2], handles[3]);
}
#if !defined(USE_GLES2) #if !defined(USE_GLES2)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
template<int N> template<int N>

View File

@ -113,10 +113,6 @@ void expandTexSecondPass(const GLMesh &mesh,
prefilled_tex[1], prefilled_tex[2]); prefilled_tex[1], prefilled_tex[2]);
} }
template<>
void expandTexSecondPass<GrassMat>(const GLMesh &mesh,
const std::vector<GLuint> &prefilled_tex);
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Give acces textures for second rendering pass in shaders /** Give acces textures for second rendering pass in shaders
* without first binding them in order to reduce driver overhead. * without first binding them in order to reduce driver overhead.
@ -133,10 +129,6 @@ void expandHandlesSecondPass(const std::vector<uint64_t> &handles)
handles[0], handles[1], handles[2]); handles[0], handles[1], handles[2]);
} }
template<>
void expandHandlesSecondPass<GrassMat>(const std::vector<uint64_t> &handles);
#if !defined(USE_GLES2) #if !defined(USE_GLES2)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** /**

View File

@ -89,49 +89,6 @@ void renderMeshes2ndPass( const std::vector<uint64_t> &Prefilled_Handle,
} }
} // renderMeshes2ndPass } // renderMeshes2ndPass
// ----------------------------------------------------------------------------
template<>
void renderMeshes2ndPass<GrassMat, 4, 3, 1>
(const std::vector<uint64_t> &Prefilled_Handle,
const std::vector<GLuint> &Prefilled_Tex)
{
auto &meshes = GrassMat::List::getInstance()->SolidPass;
GrassMat::SecondPassShader::getInstance()->use();
if (CVS->isARBBaseInstanceUsable())
glBindVertexArray(VAOManager::getInstance()->getVAO(GrassMat::VertexType));
for (unsigned i = 0; i < meshes.size(); i++)
{
GLMesh &mesh = *(std::get<0>(meshes.at(i)));
if (!CVS->isARBBaseInstanceUsable())
glBindVertexArray(mesh.vao);
if (mesh.VAOType != GrassMat::VertexType)
{
#ifdef DEBUG
Log::error("Materials", "Wrong vertex Type associed to pass 2 "
"(hint texture : %s)",
mesh.textures[0]->getName().getPath().c_str());
#endif
continue;
}
if (CVS->isAZDOEnabled())
{
HandleExpander<GrassMat::SecondPassShader>::
expand(mesh.TextureHandles, GrassMat::SecondPassTextures,
Prefilled_Handle[0], Prefilled_Handle[1],
Prefilled_Handle[2], Prefilled_Handle[3]);
}
else
{
TexExpander<GrassMat::SecondPassShader>::
expandTex(mesh, GrassMat::SecondPassTextures, Prefilled_Tex[0],
Prefilled_Tex[1], Prefilled_Tex[2], Prefilled_Tex[3]);
}
CustomUnrollArgs<4, 3, 1>::drawMesh<GrassMat::SecondPassShader>(meshes.at(i));
}
} // renderMeshes2ndPass
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
template<typename T, int...List> template<typename T, int...List>
void renderShadow(unsigned cascade) void renderShadow(unsigned cascade)

View File

@ -20,6 +20,7 @@
#include "audio/sfx_base.hpp" #include "audio/sfx_base.hpp"
#include "audio/sfx_manager.hpp" #include "audio/sfx_manager.hpp"
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp" #include "graphics/irr_driver.hpp"
#include "graphics/material.hpp" #include "graphics/material.hpp"
#include "graphics/material_manager.hpp" #include "graphics/material_manager.hpp"
@ -44,7 +45,12 @@ Explosion::Explosion(const Vec3& coord, const char* explosion_sound, const char
#ifndef SERVER_ONLY #ifndef SERVER_ONLY
ParticleKindManager* pkm = ParticleKindManager::get(); ParticleKindManager* pkm = ParticleKindManager::get();
ParticleKind* particles = pkm->getParticles(particle_file); ParticleKind* particles = pkm->getParticles(particle_file);
m_emitter = new ParticleEmitter(particles, coord, NULL); m_emitter = NULL;
if (UserConfigParams::m_graphical_effects > 1)
{
m_emitter = new ParticleEmitter(particles, coord, NULL);
}
#endif #endif
} // Explosion } // Explosion
@ -76,7 +82,8 @@ bool Explosion::updateAndDelete(float dt)
m_remaining_time -= dt; m_remaining_time -= dt;
#ifndef SERVER_ONLY #ifndef SERVER_ONLY
if (m_remaining_time < 0.0f && m_remaining_time >= -explosion_time) if (m_remaining_time < 0.0f && m_remaining_time >= -explosion_time &&
m_emitter != NULL)
{ {
scene::ISceneNode* node = m_emitter->getNode(); scene::ISceneNode* node = m_emitter->getNode();
@ -106,7 +113,7 @@ bool Explosion::updateAndDelete(float dt)
#ifndef SERVER_ONLY #ifndef SERVER_ONLY
// if framerate is very low, emit for at least a few frames, in case // if framerate is very low, emit for at least a few frames, in case
// burst time is lower than the time of 1 frame // burst time is lower than the time of 1 frame
if (m_emission_frames > 2) if (m_emission_frames > 2 && m_emitter != NULL)
{ {
// Stop the emitter and wait a little while for all particles to have time to fade out // Stop the emitter and wait a little while for all particles to have time to fade out
m_emitter->getNode()->getEmitter()->setMinParticlesPerSecond(0); m_emitter->getNode()->getEmitter()->setMinParticlesPerSecond(0);

View File

@ -317,8 +317,9 @@ void AbstractGeometryPasses::renderTransparent(const DrawCalls& draw_calls,
glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
video::E_VERTEX_TYPE cur_dis_type = video::EVT_2TCOORDS;
if (CVS->isARBBaseInstanceUsable()) if (CVS->isARBBaseInstanceUsable())
glBindVertexArray(VAOManager::getInstance()->getVAO(video::EVT_2TCOORDS)); glBindVertexArray(VAOManager::getInstance()->getVAO(cur_dis_type));
// Generate displace mask // Generate displace mask
// Use RTT_TMP4 as displace mask // Use RTT_TMP4 as displace mask
if (ListDisplacement::getInstance()->size() > 0) if (ListDisplacement::getInstance()->size() > 0)
@ -334,12 +335,10 @@ void AbstractGeometryPasses::renderTransparent(const DrawCalls& draw_calls,
glBindVertexArray(mesh.vao); glBindVertexArray(mesh.vao);
const core::matrix4 &AbsoluteTransformation const core::matrix4 &AbsoluteTransformation
= std::get<1>(ListDisplacement::getInstance()->at(i)); = std::get<1>(ListDisplacement::getInstance()->at(i));
if (mesh.VAOType != video::EVT_2TCOORDS) if (mesh.VAOType != cur_dis_type && CVS->isARBBaseInstanceUsable())
{ {
#ifdef DEBUG cur_dis_type = mesh.VAOType;
Log::error("Materials", "Displacement has wrong vertex type"); glBindVertexArray(VAOManager::getInstance()->getVAO(cur_dis_type));
#endif
continue;
} }
GLenum ptype = mesh.PrimitiveType; GLenum ptype = mesh.PrimitiveType;
@ -357,6 +356,9 @@ void AbstractGeometryPasses::renderTransparent(const DrawCalls& draw_calls,
displace_framebuffer.bind(); displace_framebuffer.bind();
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
} }
cur_dis_type = video::EVT_2TCOORDS;
if (CVS->isARBBaseInstanceUsable())
glBindVertexArray(VAOManager::getInstance()->getVAO(cur_dis_type));
for (unsigned i = 0; i < ListDisplacement::getInstance()->size(); i++) for (unsigned i = 0; i < ListDisplacement::getInstance()->size(); i++)
{ {
const GLMesh &mesh = const GLMesh &mesh =
@ -365,8 +367,11 @@ void AbstractGeometryPasses::renderTransparent(const DrawCalls& draw_calls,
glBindVertexArray(mesh.vao); glBindVertexArray(mesh.vao);
const core::matrix4 &AbsoluteTransformation = const core::matrix4 &AbsoluteTransformation =
std::get<1>(ListDisplacement::getInstance()->at(i)); std::get<1>(ListDisplacement::getInstance()->at(i));
if (mesh.VAOType != video::EVT_2TCOORDS) if (mesh.VAOType != cur_dis_type && CVS->isARBBaseInstanceUsable())
continue; {
cur_dis_type = mesh.VAOType;
glBindVertexArray(VAOManager::getInstance()->getVAO(cur_dis_type));
}
GLenum ptype = mesh.PrimitiveType; GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType; GLenum itype = mesh.IndexType;
@ -379,6 +384,7 @@ void AbstractGeometryPasses::renderTransparent(const DrawCalls& draw_calls,
mesh.textures[0]->getOpenGLTextureName()); mesh.textures[0]->getOpenGLTextureName());
DisplaceShader::getInstance()->use(); DisplaceShader::getInstance()->use();
DisplaceShader::getInstance()->setUniforms(AbsoluteTransformation, DisplaceShader::getInstance()->setUniforms(AbsoluteTransformation,
mesh.texture_trans,
core::vector2df(cb->getDirX(), cb->getDirY()), core::vector2df(cb->getDirX(), cb->getDirY()),
core::vector2df(cb->getDir2X(), cb->getDir2Y())); core::vector2df(cb->getDir2X(), cb->getDir2Y()));

View File

@ -365,18 +365,16 @@ public:
{ {
#if defined(__linux__) && !defined(ANDROID) #if defined(__linux__) && !defined(ANDROID)
if(m_os!="linux") return false; if(m_os!="linux") return false;
#endif #elif defined(WIN32)
#ifdef WIN32
if(m_os!="windows") return false; if(m_os!="windows") return false;
#endif #elif defined(__APPLE__)
#ifdef __APPLE__
if(m_os!="osx") return false; if(m_os!="osx") return false;
#endif #elif defined(BSD)
#ifdef BSD
if(m_os!="bsd") return false; if(m_os!="bsd") return false;
#endif #elif defined(ANDROID)
#ifdef ANDROID
if(m_os!="android") return false; if(m_os!="android") return false;
#else
return false;
#endif #endif
} // m_os.size()>0 } // m_os.size()>0

View File

@ -37,6 +37,7 @@
#include "graphics/stk_animated_mesh.hpp" #include "graphics/stk_animated_mesh.hpp"
#include "graphics/stk_billboard.hpp" #include "graphics/stk_billboard.hpp"
#include "graphics/stk_mesh_loader.hpp" #include "graphics/stk_mesh_loader.hpp"
#include "graphics/sp_mesh_loader.hpp"
#include "graphics/stk_mesh_scene_node.hpp" #include "graphics/stk_mesh_scene_node.hpp"
#include "graphics/stk_tex_manager.hpp" #include "graphics/stk_tex_manager.hpp"
#include "graphics/stk_texture.hpp" #include "graphics/stk_texture.hpp"
@ -605,6 +606,9 @@ void IrrDriver::initDevice()
STKMeshLoader* sml = new STKMeshLoader(m_scene_manager); STKMeshLoader* sml = new STKMeshLoader(m_scene_manager);
m_scene_manager->addExternalMeshLoader(sml); m_scene_manager->addExternalMeshLoader(sml);
sml->drop(); sml->drop();
SPMeshLoader* spml = new SPMeshLoader(m_scene_manager);
m_scene_manager->addExternalMeshLoader(spml);
spml->drop();
m_actual_screen_size = m_video_driver->getCurrentRenderTargetSize(); m_actual_screen_size = m_video_driver->getCurrentRenderTargetSize();
@ -1018,11 +1022,11 @@ void IrrDriver::applyResolutionSettings()
GUIEngine::addLoadingIcon( GUIEngine::addLoadingIcon(
irr_driver->getTexture(file_manager->getAsset(FileManager::GUI,"gift.png")) ); irr_driver->getTexture(file_manager->getAsset(FileManager::GUI,"gift.png")) );
file_manager->popTextureSearchPath();
kart_properties_manager->loadAllKarts(); kart_properties_manager->loadAllKarts();
attachment_manager->loadModels(); attachment_manager->loadModels();
file_manager->popTextureSearchPath();
std::string banana = file_manager->getAsset(FileManager::GUI, "banana.png"); std::string banana = file_manager->getAsset(FileManager::GUI, "banana.png");
GUIEngine::addLoadingIcon(irr_driver->getTexture(banana) ); GUIEngine::addLoadingIcon(irr_driver->getTexture(banana) );
// No need to reload cached track data (track_manager->cleanAllCachedData // No need to reload cached track data (track_manager->cleanAllCachedData

View File

@ -618,10 +618,10 @@ void Material::initCustomSFX(const XMLNode *sfx)
{ {
// The directory for the track was added to the model search path // The directory for the track was added to the model search path
// so just misuse the getModelFile function // so just misuse the searchModel function
const std::string full_path = file_manager->getAsset(FileManager::MODEL, std::string path = file_manager->searchModel(filename);
filename); path = StringUtils::getPath(path);
SFXBuffer* buffer = SFXManager::get()->loadSingleSfx(sfx, full_path); SFXBuffer* buffer = SFXManager::get()->loadSingleSfx(sfx, path);
if (buffer != NULL) if (buffer != NULL)
{ {

View File

@ -329,7 +329,7 @@ InstancedRefShadowShader::InstancedRefShadowShader()
// ============================================================================ // ============================================================================
DisplaceMaskShader::DisplaceMaskShader() DisplaceMaskShader::DisplaceMaskShader()
{ {
loadProgram(OBJECT, GL_VERTEX_SHADER, "displace.vert", loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert",
GL_FRAGMENT_SHADER, "white.frag"); GL_FRAGMENT_SHADER, "white.frag");
assignUniforms("ModelMatrix"); assignUniforms("ModelMatrix");
} // DisplaceMaskShader } // DisplaceMaskShader
@ -337,9 +337,9 @@ DisplaceMaskShader::DisplaceMaskShader()
// ============================================================================ // ============================================================================
DisplaceShader::DisplaceShader() DisplaceShader::DisplaceShader()
{ {
loadProgram(OBJECT, GL_VERTEX_SHADER, "displace.vert", loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert",
GL_FRAGMENT_SHADER, "displace.frag"); GL_FRAGMENT_SHADER, "displace.frag");
assignUniforms("ModelMatrix", "dir", "dir2"); assignUniforms("ModelMatrix", "texture_trans", "dir", "dir2");
assignSamplerNames(0, "displacement_tex", ST_BILINEAR_FILTERED, assignSamplerNames(0, "displacement_tex", ST_BILINEAR_FILTERED,
1, "color_tex", ST_BILINEAR_FILTERED, 1, "color_tex", ST_BILINEAR_FILTERED,
2, "mask_tex", ST_BILINEAR_FILTERED, 2, "mask_tex", ST_BILINEAR_FILTERED,
@ -432,10 +432,9 @@ GrassPass2Shader::GrassPass2Shader()
assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED,
1, "SpecularMap", ST_NEAREST_FILTERED, 1, "SpecularMap", ST_NEAREST_FILTERED,
2, "SSAO", ST_BILINEAR_FILTERED, 2, "SSAO", ST_BILINEAR_FILTERED,
3, "dtex", ST_NEAREST_FILTERED, 3, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED,
4, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED, 4, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED,
5, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, 5, "colorization_mask",
6, "colorization_mask",
ST_TRILINEAR_ANISOTROPIC_FILTERED); ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // GrassPass2Shader } // GrassPass2Shader
@ -448,10 +447,9 @@ InstancedGrassPass2Shader::InstancedGrassPass2Shader()
assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED,
1, "SpecularMap", ST_NEAREST_FILTERED, 1, "SpecularMap", ST_NEAREST_FILTERED,
2, "SSAO", ST_BILINEAR_FILTERED, 2, "SSAO", ST_BILINEAR_FILTERED,
3, "dtex", ST_NEAREST_FILTERED, 3, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED,
4, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED, 4, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED,
5, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, 5, "colorization_mask",
6, "colorization_mask",
ST_TRILINEAR_ANISOTROPIC_FILTERED); ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // InstancedGrassPass2Shader } // InstancedGrassPass2Shader

View File

@ -212,7 +212,8 @@ public:
// ============================================================================ // ============================================================================
class DisplaceShader : public TextureShader<DisplaceShader, 4, core::matrix4, class DisplaceShader : public TextureShader<DisplaceShader, 4, core::matrix4,
core::vector2df, core::vector2df> core::vector2df, core::vector2df,
core::vector2df>
{ {
public: public:
DisplaceShader(); DisplaceShader();
@ -260,7 +261,7 @@ public:
}; // InstancedGrassShadowShader }; // InstancedGrassShadowShader
// ============================================================================ // ============================================================================
class GrassPass2Shader : public TextureShader<GrassPass2Shader, 7, class GrassPass2Shader : public TextureShader<GrassPass2Shader, 6,
core::matrix4, core::vector3df, core::matrix4, core::vector3df,
core::vector2df> core::vector2df>
{ {
@ -270,7 +271,7 @@ public:
// ============================================================================ // ============================================================================
class InstancedGrassPass2Shader class InstancedGrassPass2Shader
: public TextureShader<InstancedGrassPass2Shader, 7, core::vector3df> : public TextureShader<InstancedGrassPass2Shader, 6, core::vector3df>
{ {
public: public:
InstancedGrassPass2Shader(); InstancedGrassPass2Shader();

View File

@ -33,6 +33,7 @@
#include "graphics/rtts.hpp" #include "graphics/rtts.hpp"
#include "graphics/shaders.hpp" #include "graphics/shaders.hpp"
#include "graphics/skybox.hpp" #include "graphics/skybox.hpp"
#include "graphics/stk_billboard.hpp"
#include "graphics/stk_mesh_scene_node.hpp" #include "graphics/stk_mesh_scene_node.hpp"
#include "graphics/spherical_harmonics.hpp" #include "graphics/spherical_harmonics.hpp"
#include "items/item_manager.hpp" #include "items/item_manager.hpp"
@ -58,12 +59,9 @@ void ShaderBasedRenderer::setRTT(RTT* rtts)
rtts->getDepthStencilTexture()); rtts->getDepthStencilTexture());
m_geometry_passes->setFirstPassRenderTargets(prefilled_textures, m_geometry_passes->setFirstPassRenderTargets(prefilled_textures,
rtts->getPrefilledHandles()); rtts->getPrefilledHandles());
m_rtts = rtts;
}
else if (rtts == NULL)
{
m_rtts = NULL;
} }
m_rtts = rtts;
} //setRTT } //setRTT
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -155,13 +153,6 @@ void ShaderBasedRenderer::prepareForwardRenderer()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
} }
// ----------------------------------------------------------------------------
void ShaderBasedRenderer::updateLightsInfo(scene::ICameraSceneNode * const camnode,
float dt)
{
m_lighting_passes.updateLightsInfo(camnode, dt);
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Upload lighting info to the dedicated uniform buffer /** Upload lighting info to the dedicated uniform buffer
*/ */
@ -259,6 +250,10 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode,
m_poly_count[SOLID_NORMAL_AND_DEPTH_PASS] += solid_poly_count; m_poly_count[SOLID_NORMAL_AND_DEPTH_PASS] += solid_poly_count;
m_poly_count[SHADOW_PASS] += shadow_poly_count; m_poly_count[SHADOW_PASS] += shadow_poly_count;
PROFILER_POP_CPU_MARKER(); PROFILER_POP_CPU_MARKER();
// For correct position of headlight in karts
PROFILER_PUSH_CPU_MARKER("Update Light Info", 0xFF, 0x0, 0x0);
m_lighting_passes.updateLightsInfo(camnode, dt);
PROFILER_POP_CPU_MARKER();
#if !defined(USE_GLES2) #if !defined(USE_GLES2)
// Shadows // Shadows
@ -659,6 +654,7 @@ ShaderBasedRenderer::~ShaderBasedRenderer()
delete m_skybox; delete m_skybox;
delete m_rtts; delete m_rtts;
ShaderFilesManager::kill(); ShaderFilesManager::kill();
STKBillboard::destroyBillboardVAO();
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -807,9 +803,6 @@ void ShaderBasedRenderer::render(float dt)
if (!CVS->isDefferedEnabled()) if (!CVS->isDefferedEnabled())
glEnable(GL_FRAMEBUFFER_SRGB); glEnable(GL_FRAMEBUFFER_SRGB);
PROFILER_PUSH_CPU_MARKER("Update Light Info", 0xFF, 0x0, 0x0);
m_lighting_passes.updateLightsInfo(camnode, dt);
PROFILER_POP_CPU_MARKER();
PROFILER_PUSH_CPU_MARKER("UBO upload", 0x0, 0xFF, 0x0); PROFILER_PUSH_CPU_MARKER("UBO upload", 0x0, 0xFF, 0x0);
computeMatrixesAndCameras(camnode, m_rtts->getWidth(), m_rtts->getHeight()); computeMatrixesAndCameras(camnode, m_rtts->getWidth(), m_rtts->getHeight());
m_shadow_matrices.updateSunOrthoMatrices(); m_shadow_matrices.updateSunOrthoMatrices();
@ -921,7 +914,6 @@ void ShaderBasedRenderer::renderToTexture(GL3RenderTarget *render_target,
irr_driver->getSceneManager()->setActiveCamera(camera); irr_driver->getSceneManager()->setActiveCamera(camera);
computeMatrixesAndCameras(camera, m_rtts->getWidth(), m_rtts->getHeight()); computeMatrixesAndCameras(camera, m_rtts->getWidth(), m_rtts->getHeight());
updateLightsInfo(camera, dt);
if (CVS->isARBUniformBufferObjectUsable()) if (CVS->isARBUniformBufferObjectUsable())
uploadLightingData(); uploadLightingData();

View File

@ -61,9 +61,6 @@ private:
void prepareForwardRenderer(); void prepareForwardRenderer();
void updateLightsInfo(irr::scene::ICameraSceneNode * const camnode,
float dt);
void uploadLightingData() const; void uploadLightingData() const;
void computeMatrixesAndCameras(scene::ICameraSceneNode * const camnode, void computeMatrixesAndCameras(scene::ICameraSceneNode * const camnode,

View File

@ -0,0 +1,654 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2017 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/sp_mesh_loader.hpp"
#include "graphics/stk_tex_manager.hpp"
#include "utils/constants.hpp"
const uint8_t VERSION_NOW = 1;
#include <algorithm>
#include <cmath>
#include <IVideoDriver.h>
#include <IFileSystem.h>
// ----------------------------------------------------------------------------
bool SPMeshLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension(filename, "spm");
} // isALoadableFileExtension
// ----------------------------------------------------------------------------
scene::IAnimatedMesh* SPMeshLoader::createMesh(io::IReadFile* f)
{
if (!IS_LITTLE_ENDIAN)
{
Log::error("SPMeshLoader", "Not little endian machine.");
return NULL;
}
if (f == NULL)
{
return NULL;
}
m_bind_frame = 0;
m_joint_count = 0;
//m_frame_count = 0;
m_mesh = NULL;
m_mesh = m_scene_manager->createSkinnedMesh();
io::IFileSystem* fs = m_scene_manager->getFileSystem();
std::string base_path = fs->getFileDir(f->getFileName()).c_str();
std::string header;
header.resize(2);
f->read(&header.front(), 2);
if (header != "SP")
{
Log::error("SPMeshLoader", "Not a spm file.");
m_mesh->drop();
return NULL;
}
uint8_t byte = 0;
f->read(&byte, 1);
uint8_t version = byte >> 3;
if (version != VERSION_NOW)
{
Log::error("SPMeshLoader", "Version mismatch, file %d SP %d", version,
VERSION_NOW);
m_mesh->drop();
return NULL;
}
byte &= ~0x08;
header = byte == 0 ? "SPMS" : byte == 1 ? "SPMA" : "SPMN";
if (header == "SPMS")
{
Log::error("SPMeshLoader", "Space partitioned mesh not supported.");
m_mesh->drop();
return NULL;
}
f->read(&byte, 1);
bool read_normal = byte & 0x01;
bool read_vcolor = byte >> 1 & 0x01;
bool read_tangent = byte >> 2 & 0x01;
const bool is_skinned = header == "SPMA";
const SPVertexType vt = is_skinned ? SPVT_SKINNED : SPVT_NORMAL;
float bbox[6];
f->read(bbox, 24);
uint16_t size_num = 0;
f->read(&size_num, 2);
unsigned id = 0;
std::unordered_map<unsigned, std::tuple<video::SMaterial, bool,
bool> > mat_map;
while (size_num != 0)
{
uint8_t tex_size;
std::string tex_name_1, tex_name_2;
f->read(&tex_size, 1);
if (tex_size > 0)
{
tex_name_1.resize(tex_size);
f->read(&tex_name_1.front(), tex_size);
}
f->read(&tex_size, 1);
if (tex_size > 0)
{
tex_name_2.resize(tex_size);
f->read(&tex_name_2.front(), tex_size);
}
TexConfig mtc(true/*srgb*/, false/*premul_alpha*/, true/*mesh_tex*/,
true/*set_material*/);
video::ITexture* textures[2] = { NULL, NULL };
if (!tex_name_1.empty())
{
std::string full_path = base_path + "/" + tex_name_1;
if (fs->existFile(full_path.c_str()))
{
tex_name_1 = full_path;
}
video::ITexture* tex = STKTexManager::getInstance()
->getTexture(tex_name_1, &mtc);
if (tex != NULL)
{
textures[0] = tex;
}
}
if (!tex_name_2.empty())
{
std::string full_path = base_path + "/" + tex_name_2;
if (fs->existFile(full_path.c_str()))
{
tex_name_2 = full_path;
}
textures[1] = STKTexManager::getInstance()->getTexture(tex_name_2,
&mtc);
}
video::SMaterial m;
m.MaterialType = video::EMT_SOLID;
if (textures[0] != NULL)
{
m.setTexture(0, textures[0]);
}
if (textures[1] != NULL)
{
m.setTexture(1, textures[1]);
}
mat_map[id] =
std::make_tuple(m, !tex_name_1.empty(), !tex_name_2.empty());
size_num--;
id++;
}
f->read(&size_num, 2);
while (size_num != 0)
{
uint16_t mat_size;
f->read(&mat_size, 2);
while (mat_size != 0)
{
uint32_t vertices_count, indices_count;
uint16_t mat_id;
f->read(&vertices_count, 4);
if (vertices_count > 65535)
{
Log::error("SPMeshLoader", "32bit index not supported.");
m_mesh->drop();
return NULL;
}
f->read(&indices_count, 4);
f->read(&mat_id, 2);
assert(mat_id < mat_map.size());
decompress(f, vertices_count, indices_count, read_normal,
read_vcolor, read_tangent, std::get<1>(mat_map[mat_id]),
std::get<2>(mat_map[mat_id]), vt,
std::get<0>(mat_map[mat_id]));
mat_size--;
}
if (header == "SPMS")
{
// Reserved, never used
assert(false);
f->read(bbox, 24);
}
size_num--;
}
if (header == "SPMA")
{
createAnimationData(f);
convertIrrlicht();
}
else if (header == "SPMS")
{
// Reserved, never used
assert(false);
uint16_t pre_computed_size = 0;
f->read(&pre_computed_size, 2);
}
m_mesh->finalize();
m_all_armatures.clear();
m_to_bind_pose_matrices.clear();
m_joints.clear();
return m_mesh;
} // createMesh
// ----------------------------------------------------------------------------
void SPMeshLoader::decompress(irr::io::IReadFile* spm, unsigned vertices_count,
unsigned indices_count, bool read_normal,
bool read_vcolor, bool read_tangent, bool uv_one,
bool uv_two, SPVertexType vt,
const video::SMaterial& m)
{
assert(vertices_count != 0);
assert(indices_count != 0);
scene::SSkinMeshBuffer* mb = m_mesh->addMeshBuffer();
if (uv_two)
{
mb->convertTo2TCoords();
}
using namespace MiniGLM;
const unsigned idx_size = vertices_count > 255 ? 2 : 1;
char tmp[8] = {};
std::vector<std::pair<std::array<short, 4>, std::array<float, 4> > >
cur_joints;
for (unsigned i = 0; i < vertices_count; i++)
{
video::S3DVertex2TCoords vertex;
// 3 * float position
spm->read(&vertex.Pos, 12);
if (read_normal)
{
// 3 10 + 2 bits normal
uint32_t packed;
spm->read(&packed, 4);
vertex.Normal = extract3Int10Bit(packed);
}
if (read_vcolor)
{
// Color identifier
uint8_t ci;
spm->read(&ci, 1);
if (ci == 128)
{
// All white
vertex.Color = video::SColor(255, 255, 255, 255);
}
else
{
uint8_t r, g, b;
spm->read(&r, 1);
spm->read(&g, 1);
spm->read(&b, 1);
vertex.Color = video::SColor(255, r, g, b);
}
}
else
{
vertex.Color = video::SColor(255, 255, 255, 255);
}
if (uv_one)
{
short hf[2];
spm->read(hf, 4);
vertex.TCoords.X = toFloat32(hf[0]);
vertex.TCoords.Y = toFloat32(hf[1]);
assert(!std::isnan(vertex.TCoords.X));
assert(!std::isnan(vertex.TCoords.Y));
if (uv_two)
{
spm->read(hf, 4);
vertex.TCoords2.X = toFloat32(hf[0]);
vertex.TCoords2.Y = toFloat32(hf[1]);
assert(!std::isnan(vertex.TCoords2.X));
assert(!std::isnan(vertex.TCoords2.Y));
}
if (read_tangent)
{
// Unused, tangents are re-calculated anyway
spm->read(tmp, 8);
}
}
if (vt == SPVT_SKINNED)
{
std::array<short, 4> joint_idx;
spm->read(joint_idx.data(), 8);
spm->read(tmp, 8);
std::array<float, 4> joint_weight = {};
for (int j = 0; j < 8; j += 2)
{
short hf;
memcpy(&hf, tmp + j, 2);
const unsigned idx = j >> 1;
joint_weight[idx] = toFloat32(hf);
assert(!std::isnan(joint_weight[idx]));
}
cur_joints.emplace_back(joint_idx, joint_weight);
}
if (uv_two)
{
mb->Vertices_2TCoords.push_back(vertex);
}
else
{
mb->Vertices_Standard.push_back(vertex);
}
}
if (vt == SPVT_SKINNED)
{
m_joints.emplace_back(std::move(cur_joints));
}
if (m.TextureLayer[0].Texture != NULL)
{
mb->Material = m;
}
mb->Indices.set_used(indices_count);
if (idx_size == 2)
{
spm->read(mb->Indices.pointer(), indices_count * 2);
}
else
{
std::vector<uint8_t> tmp_idx;
tmp_idx.resize(indices_count);
spm->read(tmp_idx.data(), indices_count);
for (unsigned i = 0; i < indices_count; i++)
{
mb->Indices[i] = tmp_idx[i];
}
}
if (!read_normal)
{
for (unsigned i = 0; i < mb->Indices.size(); i += 3)
{
core::plane3df p(mb->getVertex(mb->Indices[i])->Pos,
mb->getVertex(mb->Indices[i + 1])->Pos,
mb->getVertex(mb->Indices[i + 2])->Pos);
mb->getVertex(mb->Indices[i])->Normal += p.Normal;
mb->getVertex(mb->Indices[i + 1])->Normal += p.Normal;
mb->getVertex(mb->Indices[i + 2])->Normal += p.Normal;
}
for (unsigned i = 0; i < mb->getVertexCount(); i++)
{
mb->getVertex(i)->Normal.normalize();
}
}
} // decompress
// ----------------------------------------------------------------------------
void SPMeshLoader::createAnimationData(irr::io::IReadFile* spm)
{
if (m_joints.empty())
{
Log::error("SPMeshLoader", "No joints are added.");
return;
}
assert(m_joints.size() == m_mesh->getMeshBufferCount());
uint8_t armature_size = 0;
spm->read(&armature_size, 1);
assert(armature_size > 0);
m_bind_frame = 0;
spm->read(&m_bind_frame, 2);
m_all_armatures.resize(armature_size);
for (unsigned i = 0; i < armature_size; i++)
{
m_all_armatures[i].read(spm);
}
for (unsigned i = 0; i < armature_size; i++)
{
//m_frame_count = std::max(m_frame_count,
// (unsigned)m_all_armatures[i].m_frame_pose_matrices.back().first);
m_joint_count += m_all_armatures[i].m_joint_used;
}
m_to_bind_pose_matrices.resize(m_joint_count);
unsigned accumulated_joints = 0;
for (unsigned i = 0; i < armature_size; i++)
{
m_all_armatures[i].getPose((float)m_bind_frame,
&m_to_bind_pose_matrices[accumulated_joints]);
accumulated_joints += m_all_armatures[i].m_joint_used;
}
for (unsigned i = 0; i < m_to_bind_pose_matrices.size(); i++)
{
m_to_bind_pose_matrices[i].makeInverse();
}
for (unsigned i = 0; i < m_mesh->getMeshBufferCount(); i++)
{
for (unsigned j = 0; j < m_joints[i].size(); j++)
{
if (!(m_joints[i][j].first[0] == -1 ||
m_joints[i][j].second[0] == 0.0f))
{
core::vector3df bind_pos, bind_nor;
for (unsigned k = 0; k < 4; k++)
{
if (m_joints[i][j].second[k] == 0.0f)
{
break;
}
core::vector3df cur_pos, cur_nor;
m_to_bind_pose_matrices[m_joints[i][j].first[k]]
.transformVect(cur_pos,
m_mesh->getMeshBuffers()[i]->getVertex(j)->Pos);
bind_pos += cur_pos * m_joints[i][j].second[k];
m_to_bind_pose_matrices[m_joints[i][j].first[k]]
.rotateVect(cur_nor,
m_mesh->getMeshBuffers()[i]->getVertex(j)->Normal);
bind_nor += cur_nor * m_joints[i][j].second[k];
}
m_mesh->getMeshBuffers()[i]->getVertex(j)->Pos = bind_pos;
m_mesh->getMeshBuffers()[i]->getVertex(j)->Normal = bind_nor;
}
}
}
} // createAnimationData
// ----------------------------------------------------------------------------
void SPMeshLoader::convertIrrlicht()
{
unsigned total_joints = 0;
for (unsigned i = 0; i < m_all_armatures.size(); i++)
{
total_joints += (unsigned)m_all_armatures[i].m_joint_names.size();
}
for (unsigned i = 0; i < total_joints; i++)
{
m_mesh->addJoint(NULL);
}
core::array<scene::ISkinnedMesh::SJoint*>& joints = m_mesh->getAllJoints();
std::vector<int> used_joints_map;
used_joints_map.resize(m_joint_count);
total_joints = 0;
unsigned used_joints = 0;
for (unsigned i = 0; i < m_all_armatures.size(); i++)
{
for (unsigned j = 0; j < m_all_armatures[i].m_joint_names.size(); j++)
{
if (m_all_armatures[i].m_joint_used > j)
{
used_joints_map[used_joints + j] = total_joints + j;
}
joints[total_joints + j]->Name =
m_all_armatures[i].m_joint_names[j].c_str();
const int p_id = m_all_armatures[i].m_parent_infos[j];
core::matrix4 tmp;
if (p_id != -1)
{
joints[total_joints + p_id]->Children.push_back
(joints[total_joints + j]);
m_all_armatures[i].m_joint_matrices[j].getInverse(tmp);
tmp = m_all_armatures[i].m_joint_matrices[p_id] * tmp;
}
else
{
m_all_armatures[i].m_joint_matrices[j].getInverse(tmp);
}
joints[total_joints + j]->LocalMatrix = tmp;
for (unsigned k = 0; k <
m_all_armatures[i].m_frame_pose_matrices.size(); k++)
{
float frame = (float)
m_all_armatures[i].m_frame_pose_matrices[k].first;
core::vector3df pos = m_all_armatures[i]
.m_frame_pose_matrices[k].second[j].m_loc;
core::quaternion q = m_all_armatures[i]
.m_frame_pose_matrices[k].second[j].m_rot;
core::vector3df scl = m_all_armatures[i]
.m_frame_pose_matrices[k].second[j].m_scale;
joints[total_joints + j]->PositionKeys.push_back({frame, pos});
joints[total_joints + j]->RotationKeys.push_back({frame, q});
joints[total_joints + j]->ScaleKeys.push_back({frame, scl});
}
}
total_joints += (unsigned)m_all_armatures[i].m_joint_names.size();
used_joints += m_all_armatures[i].m_joint_used;
}
for (unsigned i = 0; i < m_joints.size(); i++)
{
for (unsigned j = 0; j < m_joints[i].size(); j++)
{
for (unsigned k = 0; k < 4; k++)
{
if (m_joints[i][j].first[k] == -1 ||
m_joints[i][j].second[k] == 0.0f)
{
break;
}
scene::ISkinnedMesh::SWeight* w = m_mesh->addWeight
(joints[used_joints_map[m_joints[i][j].first[k]]]);
w->buffer_id = (uint16_t)i;
w->vertex_id = j;
w->strength = m_joints[i][j].second[k];
}
}
}
} // convertIrrlicht
// ----------------------------------------------------------------------------
void SPMeshLoader::Armature::read(irr::io::IReadFile* spm)
{
LocRotScale lrs;
spm->read(&m_joint_used, 2);
assert(m_joint_used > 0);
unsigned all_joints_size = 0;
spm->read(&all_joints_size, 2);
assert(all_joints_size > 0);
m_joint_names.resize(all_joints_size);
for (unsigned i = 0; i < all_joints_size; i++)
{
unsigned str_len = 0;
spm->read(&str_len, 1);
m_joint_names[i].resize(str_len);
spm->read(&m_joint_names[i].front(), str_len);
}
m_joint_matrices.resize(all_joints_size);
m_interpolated_matrices.resize(all_joints_size);
for (unsigned i = 0; i < all_joints_size; i++)
{
lrs.read(spm);
m_joint_matrices[i] = lrs.toMatrix();
}
m_world_matrices.resize(m_interpolated_matrices.size(),
std::make_pair(core::matrix4(), false));
m_parent_infos.resize(all_joints_size);
bool non_parent_bone = false;
for (unsigned i = 0; i < all_joints_size; i++)
{
int16_t info = 0;
spm->read(&info, 2);
if (info == -1)
{
non_parent_bone = true;
}
m_parent_infos[i] = info;
}
if (!non_parent_bone)
{
Log::fatal("SPMeshLoader::Armature", "Non-parent bone missing in"
"armature");
}
unsigned frame_size = 0;
spm->read(&frame_size, 2);
m_frame_pose_matrices.resize(frame_size);
for (unsigned i = 0; i < frame_size; i++)
{
m_frame_pose_matrices[i].second.resize(all_joints_size);
unsigned frame_index = 0;
spm->read(&frame_index, 2);
m_frame_pose_matrices[i].first = frame_index;
for (unsigned j = 0; j < m_frame_pose_matrices[i].second.size(); j++)
{
m_frame_pose_matrices[i].second[j].read(spm);
}
}
} // Armature::read
// ----------------------------------------------------------------------------
void SPMeshLoader::LocRotScale::read(irr::io::IReadFile* spm)
{
float tmp[10];
spm->read(&tmp, 40);
m_loc = core::vector3df(tmp[0], tmp[1], tmp[2]);
m_rot = core::quaternion(-tmp[3], -tmp[4], -tmp[5], tmp[6]);
m_rot.normalize();
m_scale = core::vector3df(tmp[7], tmp[8], tmp[9]);
} // LocRotScale::read
// ----------------------------------------------------------------------------
void SPMeshLoader::Armature::getInterpolatedMatrices(float frame)
{
if (frame < float(m_frame_pose_matrices.front().first) ||
frame >= float(m_frame_pose_matrices.back().first))
{
for (unsigned i = 0; i < m_interpolated_matrices.size(); i++)
{
m_interpolated_matrices[i] =
frame >= float(m_frame_pose_matrices.back().first) ?
m_frame_pose_matrices.back().second[i].toMatrix() :
m_frame_pose_matrices.front().second[i].toMatrix();
}
return;
}
int frame_1 = -1;
int frame_2 = -1;
float interpolation = 0.0f;
for (unsigned i = 0; i < m_frame_pose_matrices.size(); i++)
{
assert(i + 1 < m_frame_pose_matrices.size());
if (frame >= float(m_frame_pose_matrices[i].first) &&
frame < float(m_frame_pose_matrices[i + 1].first))
{
frame_1 = i;
frame_2 = i + 1;
interpolation =
(frame - float(m_frame_pose_matrices[i].first)) /
float(m_frame_pose_matrices[i + 1].first -
m_frame_pose_matrices[i].first);
break;
}
}
assert(frame_1 != -1);
assert(frame_2 != -1);
for (unsigned i = 0; i < m_interpolated_matrices.size(); i++)
{
LocRotScale interpolated;
interpolated.m_loc =
m_frame_pose_matrices[frame_2].second[i].m_loc.getInterpolated
(m_frame_pose_matrices[frame_1].second[i].m_loc, interpolation);
interpolated.m_rot.slerp
(m_frame_pose_matrices[frame_1].second[i].m_rot,
m_frame_pose_matrices[frame_2].second[i].m_rot, interpolation);
interpolated.m_scale =
m_frame_pose_matrices[frame_2].second[i].m_scale.getInterpolated
(m_frame_pose_matrices[frame_1].second[i].m_scale, interpolation);
m_interpolated_matrices[i] = interpolated.toMatrix();
}
} // Armature::getInterpolatedMatrices
// ----------------------------------------------------------------------------
void SPMeshLoader::Armature::getPose(float frame, core::matrix4* dest)
{
getInterpolatedMatrices(frame);
for (auto& p : m_world_matrices)
{
p.second = false;
}
for (unsigned i = 0; i < m_joint_used; i++)
{
dest[i] = getWorldMatrix(m_interpolated_matrices, i) *
m_joint_matrices[i];
}
} // Armature::getPose
// ----------------------------------------------------------------------------
core::matrix4 SPMeshLoader::Armature::getWorldMatrix(
const std::vector<core::matrix4>& matrix, unsigned id)
{
core::matrix4 mat = matrix[id];
int parent_id = m_parent_infos[id];
if (parent_id == -1)
{
m_world_matrices[id] = std::make_pair(mat, true);
return mat;
}
if (!m_world_matrices[parent_id].second)
{
m_world_matrices[parent_id] = std::make_pair
(getWorldMatrix(matrix, parent_id), true);
}
m_world_matrices[id] =
std::make_pair(m_world_matrices[parent_id].first * mat, true);
return m_world_matrices[id].first;
} // Armature::getWorldMatrix

View File

@ -0,0 +1,402 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2017 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_SP_MESH_LOADER_HPP
#define HEADER_SP_MESH_LOADER_HPP
#include <IMeshLoader.h>
#include <ISceneManager.h>
#include <ISkinnedMesh.h>
#include <IReadFile.h>
#include <array>
#include <cstdint>
#include <vector>
using namespace irr;
// GLM without template
namespace MiniGLM
{
// ------------------------------------------------------------------------
inline float overflow()
{
volatile float f = 1e10;
for (int i = 0; i < 10; i++)
f *= f; // this will overflow before the for loop terminates
return f;
} // overflow
// ------------------------------------------------------------------------
inline float toFloat32(short value)
{
int s = (value >> 15) & 0x00000001;
int e = (value >> 10) & 0x0000001f;
int m = value & 0x000003ff;
if (e == 0)
{
if (m == 0)
{
//
// Plus or minus zero
//
uint32_t tmp_data = (unsigned int)(s << 31);
float ret;
memcpy(&ret, &tmp_data, 4);
return ret;
}
else
{
//
// Denormalized number -- renormalize it
//
while(!(m & 0x00000400))
{
m <<= 1;
e -= 1;
}
e += 1;
m &= ~0x00000400;
}
}
else if (e == 31)
{
if (m == 0)
{
//
// Positive or negative infinity
//
uint32_t tmp_data = (unsigned int)((s << 31) | 0x7f800000);
float ret;
memcpy(&ret, &tmp_data, 4);
return ret;
}
else
{
//
// Nan -- preserve sign and significand bits
//
uint32_t tmp_data = (unsigned int)((s << 31) | 0x7f800000 |
(m << 13));
float ret;
memcpy(&ret, &tmp_data, 4);
return ret;
}
}
//
// Normalized number
//
e = e + (127 - 15);
m = m << 13;
//
// Assemble s, e and m.
//
uint32_t tmp_data = (unsigned int)((s << 31) | (e << 23) | m);
float ret;
memcpy(&ret, &tmp_data, 4);
return ret;
} // toFloat32
// ------------------------------------------------------------------------
inline short toFloat16(float const & f)
{
int i;
memcpy(&i, &f, 4);
//
// Our floating point number, f, is represented by the bit
// pattern in integer i. Disassemble that bit pattern into
// the sign, s, the exponent, e, and the significand, m.
// Shift s into the position where it will go in in the
// resulting half number.
// Adjust e, accounting for the different exponent bias
// of float and half (127 versus 15).
//
int s = (i >> 16) & 0x00008000;
int e = ((i >> 23) & 0x000000ff) - (127 - 15);
int m = i & 0x007fffff;
//
// Now reassemble s, e and m into a half:
//
if (e <= 0)
{
if (e < -10)
{
//
// E is less than -10. The absolute value of f is
// less than half_MIN (f may be a small normalized
// float, a denormalized float or a zero).
//
// We convert f to a half zero.
//
return short(s);
}
//
// E is between -10 and 0. F is a normalized float,
// whose magnitude is less than __half_NRM_MIN.
//
// We convert f to a denormalized half.
//
m = (m | 0x00800000) >> (1 - e);
//
// Round to nearest, round "0.5" up.
//
// Rounding may cause the significand to overflow and make
// our number normalized. Because of the way a half's bits
// are laid out, we don't have to treat this case separately;
// the code below will handle it correctly.
//
if (m & 0x00001000)
m += 0x00002000;
//
// Assemble the half from s, e (zero) and m.
//
return short(s | (m >> 13));
}
else if (e == 0xff - (127 - 15))
{
if (m == 0)
{
//
// F is an infinity; convert f to a half
// infinity with the same sign as f.
//
return short(s | 0x7c00);
}
else
{
//
// F is a NAN; we produce a half NAN that preserves
// the sign bit and the 10 leftmost bits of the
// significand of f, with one exception: If the 10
// leftmost bits are all zero, the NAN would turn
// into an infinity, so we have to set at least one
// bit in the significand.
//
m >>= 13;
return short(s | 0x7c00 | m | (m == 0));
}
}
else
{
//
// E is greater than zero. F is a normalized float.
// We try to convert f to a normalized half.
//
//
// Round to nearest, round "0.5" up
//
if (m & 0x00001000)
{
m += 0x00002000;
if (m & 0x00800000)
{
m = 0; // overflow in significand,
e += 1; // adjust exponent
}
}
//
// Handle exponent overflow
//
if (e > 30)
{
overflow(); // Cause a hardware floating point overflow;
return short(s | 0x7c00);
// if this returns, the half becomes an
} // infinity with the same sign as f.
//
// Assemble the half from s, e and m.
//
return short(s | (e << 10) | (m >> 13));
}
} // toFloat16
// ------------------------------------------------------------------------
inline uint32_t vectorTo3Int10Bit(const irr::core::vector3df& vec)
{
int part;
uint32_t sum;
float v;
sum = 0;
v = fminf(1.0, fmaxf(-1.0, vec.X));
if (v > 0.0)
{
part = (int)((v * 511.0) + 0.5);
}
else
{
part = (int)((v * 512.0) - 0.5);
}
sum |= ((uint32_t)part & 1023) << 0;
v = fminf(1.0, fmaxf(-1.0, vec.Y));
if (v > 0.0)
{
part = (int)((v * 511.0) + 0.5);
}
else
{
part = (int)((v * 512.0) - 0.5);
}
sum |= ((uint32_t)part & 1023) << 10;
v = fminf(1.0, fmaxf(-1.0, vec.Z));
if (v > 0.0)
{
part = (int)((v * 511.0) + 0.5);
}
else
{
part = (int)((v * 512.0) - 0.5);
}
sum |= ((uint32_t)part & 1023) << 20;
v = 0.0f;
part = (int)((v * 2.0) - 0.5);
sum |= ((uint32_t)part & 3) << 30;
return sum;
} // vectorTo3Int10Bit
// ------------------------------------------------------------------------
inline core::vector3df extract3Int10Bit(uint32_t sum)
{
core::vector3df ret;
int part = sum & 1023;
if (part & 512)
{
ret.X = (float)(1024 - part) * (-1.0f / 512.0f);
}
else
{
ret.X = (float)part * (1.0f / 511.0f);
}
part = (sum >> 10) & 1023;
if (part & 512)
{
ret.Y = (float)(1024 - part) * (-1.0f / 512.0f);
}
else
{
ret.Y = (float)part * (1.0f / 511.0f);
}
part = (sum >> 20) & 1023;
if (part & 512)
{
ret.Z = (float)(1024 - part) * (-1.0f / 512.0f);
}
else
{
ret.Z = (float)part * (1.0f / 511.0f);
}
return ret.normalize();
} // extract3Int10Bit
}
class SPMeshLoader : public scene::IMeshLoader
{
private:
// ------------------------------------------------------------------------
struct LocRotScale
{
core::vector3df m_loc;
core::quaternion m_rot;
core::vector3df m_scale;
// --------------------------------------------------------------------
inline core::matrix4 toMatrix() const
{
core::matrix4 lm, sm, rm;
lm.setTranslation(m_loc);
sm.setScale(m_scale);
m_rot.getMatrix_transposed(rm);
return lm * rm * sm;
}
// --------------------------------------------------------------------
void read(irr::io::IReadFile* spm);
};
struct Armature
{
unsigned m_joint_used;
std::vector<std::string> m_joint_names;
std::vector<core::matrix4> m_joint_matrices;
std::vector<core::matrix4> m_interpolated_matrices;
std::vector<std::pair<core::matrix4, bool> > m_world_matrices;
std::vector<int> m_parent_infos;
std::vector<std::pair<int, std::vector<LocRotScale> > >
m_frame_pose_matrices;
// --------------------------------------------------------------------
void read(irr::io::IReadFile* spm);
// --------------------------------------------------------------------
void getPose(float frame, core::matrix4* dest);
// --------------------------------------------------------------------
void getInterpolatedMatrices(float frame);
// --------------------------------------------------------------------
core::matrix4 getWorldMatrix(const std::vector<core::matrix4>& matrix,
unsigned id);
};
// ------------------------------------------------------------------------
unsigned m_bind_frame, m_joint_count;//, m_frame_count;
// ------------------------------------------------------------------------
std::vector<Armature> m_all_armatures;
// ------------------------------------------------------------------------
std::vector<core::matrix4> m_to_bind_pose_matrices;
// ------------------------------------------------------------------------
enum SPVertexType: unsigned int
{
SPVT_NORMAL,
SPVT_SKINNED
};
// ------------------------------------------------------------------------
void decompress(irr::io::IReadFile* spm, unsigned vertices_count,
unsigned indices_count, bool read_normal, bool read_vcolor,
bool read_tangent, bool uv_one, bool uv_two,
SPVertexType vt, const video::SMaterial& m);
// ------------------------------------------------------------------------
void createAnimationData(irr::io::IReadFile* spm);
// ------------------------------------------------------------------------
void convertIrrlicht();
scene::ISkinnedMesh* m_mesh;
scene::ISceneManager* m_scene_manager;
std::vector<std::vector<
std::pair<std::array<short, 4>, std::array<float, 4> > > > m_joints;
public:
// ------------------------------------------------------------------------
SPMeshLoader(scene::ISceneManager* smgr) : m_scene_manager(smgr) {}
// ------------------------------------------------------------------------
virtual bool isALoadableFileExtension(const io::path& filename) const;
// ------------------------------------------------------------------------
virtual scene::IAnimatedMesh* createMesh(io::IReadFile* file);
};
#endif

View File

@ -30,10 +30,10 @@
using namespace irr; using namespace irr;
static GLuint billboardvao = 0; GLuint STKBillboard::m_billboard_vao = 0;
class BillboardShader : public TextureShader<BillboardShader, 1, core::matrix4, class BillboardShader : public TextureShader<BillboardShader, 1,
core::matrix4, core::vector3df, core::matrix4, core::vector3df,
core::dimension2df> core::dimension2df>
{ {
@ -43,18 +43,16 @@ public:
loadProgram(OBJECT, GL_VERTEX_SHADER, "billboard.vert", loadProgram(OBJECT, GL_VERTEX_SHADER, "billboard.vert",
GL_FRAGMENT_SHADER, "billboard.frag"); GL_FRAGMENT_SHADER, "billboard.frag");
assignUniforms("ModelViewMatrix", "ProjectionMatrix", "Position", assignUniforms("color_matrix", "Position", "Size");
"Size");
assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // BillboardShader } // BillboardShader
}; // BillboardShader }; // BillboardShader
// ============================================================================ // ============================================================================
void STKBillboard::createBillboardVAO()
static void createBillboardVAO()
{ {
glGenVertexArrays(1, &billboardvao); glGenVertexArrays(1, &m_billboard_vao);
glBindVertexArray(billboardvao); glBindVertexArray(m_billboard_vao);
glBindBuffer(GL_ARRAY_BUFFER, SharedGPUObjects::getBillboardVBO()); glBindBuffer(GL_ARRAY_BUFFER, SharedGPUObjects::getBillboardVBO());
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glEnableVertexAttribArray(3); glEnableVertexAttribArray(3);
@ -64,6 +62,16 @@ static void createBillboardVAO()
glBindVertexArray(0); glBindVertexArray(0);
} // createBillboardVAO } // createBillboardVAO
// ----------------------------------------------------------------------------
void STKBillboard::destroyBillboardVAO()
{
if (m_billboard_vao != 0)
{
glDeleteVertexArrays(1, &m_billboard_vao);
m_billboard_vao = 0;
}
} // destroyBillboardVAO
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
STKBillboard::STKBillboard(irr::scene::ISceneNode* parent, STKBillboard::STKBillboard(irr::scene::ISceneNode* parent,
irr::scene::ISceneManager* mgr, irr::s32 id, irr::scene::ISceneManager* mgr, irr::s32 id,
@ -75,7 +83,7 @@ STKBillboard::STKBillboard(irr::scene::ISceneNode* parent,
CBillboardSceneNode(parent, mgr, id, position, size, CBillboardSceneNode(parent, mgr, id, position, size,
colorTop, colorBottom) colorTop, colorBottom)
{ {
if (!billboardvao) if (!m_billboard_vao)
createBillboardVAO(); createBillboardVAO();
} // STKBillboard } // STKBillboard
@ -97,9 +105,9 @@ void STKBillboard::render()
return; return;
core::vector3df pos = getAbsolutePosition(); core::vector3df pos = getAbsolutePosition();
glBindVertexArray(billboardvao); glBindVertexArray(m_billboard_vao);
video::ITexture *tex = Material.getTexture(0); video::ITexture *tex = Material.getTexture(0);
if (!tex ) if (!tex)
return; return;
::Material* material = material_manager->getMaterialFor(tex, ::Material* material = material_manager->getMaterialFor(tex,
@ -109,11 +117,24 @@ void STKBillboard::render()
else else
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
video::SColor col[2];
getColor(col[0], col[1]);
const float colors[] =
{
col[1].getRed() / 255.f, col[1].getGreen() / 255.f,
col[1].getBlue() / 255.f, col[1].getAlpha() / 255.f,
col[0].getRed() / 255.f, col[0].getGreen() / 255.f,
col[0].getBlue() / 255.f, col[0].getAlpha() / 255.f,
col[1].getRed() / 255.f, col[1].getGreen() / 255.f,
col[1].getBlue() / 255.f, col[1].getAlpha() / 255.f,
col[0].getRed() / 255.f, col[0].getGreen() / 255.f,
col[0].getBlue() / 255.f, col[0].getAlpha() / 255.f,
};
core::matrix4 color_matrix;
color_matrix.setM(colors);
BillboardShader::getInstance()->use(); BillboardShader::getInstance()->use();
BillboardShader::getInstance()->setTextureUnits(tex->getOpenGLTextureName()); BillboardShader::getInstance()->setTextureUnits(tex->getOpenGLTextureName());
BillboardShader::getInstance()->setUniforms(irr_driver->getViewMatrix(), BillboardShader::getInstance()->setUniforms(color_matrix, pos, Size);
irr_driver->getProjMatrix(),
pos, Size);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0); glBindVertexArray(0);
} // render } // render

View File

@ -21,10 +21,14 @@
#include "../lib/irrlicht/source/Irrlicht/CBillboardSceneNode.h" #include "../lib/irrlicht/source/Irrlicht/CBillboardSceneNode.h"
#include <IBillboardSceneNode.h> #include <IBillboardSceneNode.h>
#include <irrTypes.h> #include <irrTypes.h>
#include "graphics/gl_headers.hpp"
#include "utils/cpp2011.hpp" #include "utils/cpp2011.hpp"
class STKBillboard : public irr::scene::CBillboardSceneNode class STKBillboard : public irr::scene::CBillboardSceneNode
{ {
private:
static GLuint m_billboard_vao;
static void createBillboardVAO();
public: public:
STKBillboard(irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, STKBillboard(irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr,
irr::s32 id, const irr::core::vector3df& position, irr::s32 id, const irr::core::vector3df& position,
@ -35,6 +39,7 @@ public:
virtual void OnRegisterSceneNode() OVERRIDE; virtual void OnRegisterSceneNode() OVERRIDE;
virtual void render() OVERRIDE; virtual void render() OVERRIDE;
static void destroyBillboardVAO();
}; // STKBillboard }; // STKBillboard
#endif #endif

View File

@ -84,8 +84,10 @@ TransparentMaterial getTransparentMaterialFromType(video::E_MATERIAL_TYPE type,
{ {
if (CVS->isDefferedEnabled()) if (CVS->isDefferedEnabled())
return TM_DISPLACEMENT; return TM_DISPLACEMENT;
else else if (tp == video::EVT_2TCOORDS)
return TM_TRANSLUCENT_2TC; return TM_TRANSLUCENT_2TC;
else
return TM_TRANSLUCENT_STD;
} }
if (material->getShaderType() == Material::SHADERTYPE_ADDITIVE) if (material->getShaderType() == Material::SHADERTYPE_ADDITIVE)
return TM_ADDITIVE; return TM_ADDITIVE;

View File

@ -147,6 +147,12 @@ video::ITexture* STKTexManager::getTexture(const std::string& path,
TexConfig* tc, bool no_upload, TexConfig* tc, bool no_upload,
bool create_if_unfound) bool create_if_unfound)
{ {
if (path.empty())
{
Log::error("STKTexManager", "Texture name is empty.");
return NULL;
}
auto ret = m_all_textures.find(path); auto ret = m_all_textures.find(path);
if (!no_upload && ret != m_all_textures.end()) if (!no_upload && ret != m_all_textures.end())
return ret->second; return ret->second;

View File

@ -32,7 +32,7 @@
#include <functional> #include <functional>
#if !defined(USE_GLES2) #if !defined(USE_GLES2)
static const uint8_t CACHE_VERSION = 1; static const uint8_t CACHE_VERSION = 2;
#endif #endif
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
STKTexture::STKTexture(const std::string& path, TexConfig* tc, bool no_upload) STKTexture::STKTexture(const std::string& path, TexConfig* tc, bool no_upload)
@ -443,10 +443,10 @@ bool STKTexture::loadCompressedTexture(const std::string& file_name)
ifs.read((char*)&cache_verison, sizeof(uint8_t)); ifs.read((char*)&cache_verison, sizeof(uint8_t));
if (cache_verison != CACHE_VERSION) if (cache_verison != CACHE_VERSION)
{ {
Log::warn("STKTexture", "%s version %d is not supported!", Log::debug("STKTexture", "%s version %d is not supported!",
file_name.c_str(), cache_verison); file_name.c_str(), cache_verison);
ifs.close(); ifs.close();
// Remove the file later if we have more version std::remove(file_name.c_str());
return false; return false;
} }
ifs.read((char*)&internal_format, sizeof(int)); ifs.read((char*)&internal_format, sizeof(int));
@ -459,8 +459,9 @@ bool STKTexture::loadCompressedTexture(const std::string& file_name)
if (ifs.fail() || m_texture_size == 0) if (ifs.fail() || m_texture_size == 0)
return false; return false;
char *data = new char[m_texture_size]; std::vector<char> compressed;
ifs.read(data, m_texture_size); compressed.resize(m_texture_size);
ifs.read(compressed.data(), m_texture_size);
if (!ifs.fail()) if (!ifs.fail())
{ {
// No on the fly reload is supported for compressed texture // No on the fly reload is supported for compressed texture
@ -475,14 +476,38 @@ bool STKTexture::loadCompressedTexture(const std::string& file_name)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
} }
glCompressedTexImage2D(GL_TEXTURE_2D, 0, internal_format, glCompressedTexImage2D(GL_TEXTURE_2D, 0, internal_format,
m_size.Width, m_size.Height, 0, m_texture_size, (GLvoid*)data); m_size.Width, m_size.Height, 0, m_texture_size, compressed.data());
glGenerateMipmap(GL_TEXTURE_2D); unsigned width = m_size.Width;
unsigned height = m_size.Height;
std::vector<std::pair<unsigned, unsigned> > mipmap_sizes;
while (true)
{
width = width < 2 ? 1 : width >> 1;
height = height < 2 ? 1 : height >> 1;
mipmap_sizes.emplace_back(width, height);
if (width == 1 && height == 1)
break;
}
for (unsigned i = 0; i < mipmap_sizes.size(); i++)
{
unsigned cur_mipmap_size = 0;
ifs.read((char*)&cur_mipmap_size, sizeof(unsigned int));
ifs.read(compressed.data(), cur_mipmap_size);
if (cur_mipmap_size == 0 || ifs.fail())
{
ifs.close();
std::remove(file_name.c_str());
return false;
}
glCompressedTexImage2D(GL_TEXTURE_2D, i + 1, internal_format,
mipmap_sizes[i].first, mipmap_sizes[i].second, 0,
cur_mipmap_size, compressed.data());
}
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
delete[] data;
ifs.close();
return true; return true;
} }
delete[] data; ifs.close();
std::remove(file_name.c_str());
#endif #endif
return false; return false;
} // loadCompressedTexture } // loadCompressedTexture
@ -515,8 +540,9 @@ void STKTexture::saveCompressedTexture(const std::string& compressed_tex)
GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint *)&m_texture_size); GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint *)&m_texture_size);
if (m_texture_size == 0) return; if (m_texture_size == 0) return;
char *data = new char[m_texture_size]; std::vector<char> compressed;
glGetCompressedTexImage(GL_TEXTURE_2D, 0, (GLvoid*)data); compressed.resize(m_texture_size);
glGetCompressedTexImage(GL_TEXTURE_2D, 0, compressed.data());
std::ofstream ofs(compressed_tex.c_str(), std::ofstream ofs(compressed_tex.c_str(),
std::ios::out | std::ios::binary); std::ios::out | std::ios::binary);
if (ofs.is_open()) if (ofs.is_open())
@ -528,10 +554,33 @@ void STKTexture::saveCompressedTexture(const std::string& compressed_tex)
ofs.write((char*)&m_orig_size.Width, sizeof(unsigned int)); ofs.write((char*)&m_orig_size.Width, sizeof(unsigned int));
ofs.write((char*)&m_orig_size.Height, sizeof(unsigned int)); ofs.write((char*)&m_orig_size.Height, sizeof(unsigned int));
ofs.write((char*)&m_texture_size, sizeof(unsigned int)); ofs.write((char*)&m_texture_size, sizeof(unsigned int));
ofs.write(data, m_texture_size); ofs.write(compressed.data(), m_texture_size);
ofs.close(); unsigned width = m_size.Width;
unsigned height = m_size.Height;
std::vector<std::pair<unsigned, unsigned> > mipmap_sizes;
while (true)
{
width = width < 2 ? 1 : width >> 1;
height = height < 2 ? 1 : height >> 1;
mipmap_sizes.emplace_back(width, height);
if (width == 1 && height == 1)
break;
}
for (unsigned i = 0; i < mipmap_sizes.size(); i++)
{
GLint cur_mipmap_size = 0;
glGetTexLevelParameteriv(GL_TEXTURE_2D, i + 1,
GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &cur_mipmap_size);
if (cur_mipmap_size == 0)
{
ofs.close();
std::remove(compressed_tex.c_str());
}
glGetCompressedTexImage(GL_TEXTURE_2D, i + 1, compressed.data());
ofs.write((char*)&cur_mipmap_size, sizeof(unsigned int));
ofs.write(compressed.data(), cur_mipmap_size);
}
} }
delete[] data;
#endif #endif
} // saveCompressedTexture } // saveCompressedTexture

View File

@ -83,12 +83,12 @@ VAOManager::~VAOManager()
} }
static void static void
resizeBufferIfNecessary(size_t &lastIndex, size_t newLastIndex, size_t bufferSize, size_t stride, GLenum type, GLuint &id, void *&Pointer) resizeBufferIfNecessary(size_t &lastIndex, size_t newLastIndex, size_t& bufferSize, size_t stride, GLenum type, GLuint &id, void *&Pointer)
{ {
if (newLastIndex * stride >= bufferSize) if (newLastIndex >= bufferSize)
{ {
while (newLastIndex >= bufferSize) while (newLastIndex >= bufferSize)
bufferSize = 2 * bufferSize + 1; bufferSize = bufferSize == 0 ? 1 : bufferSize * 2;
GLuint newVBO; GLuint newVBO;
glGenBuffers(1, &newVBO); glGenBuffers(1, &newVBO);
glBindBuffer(type, newVBO); glBindBuffer(type, newVBO);

View File

@ -65,15 +65,15 @@ void IconButtonWidget::add()
// ---- Icon // ---- Icon
if (m_texture == NULL) if (m_texture == NULL)
{ {
if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE) // Avoid warning about missing texture in case of e.g.
// screenshot widget
if (m_properties[PROP_ICON] != "")
{ {
setTexture(irr_driver->getTexture(m_properties[PROP_ICON])); if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE)
} {
else if (m_icon_path_type == ICON_PATH_TYPE_RELATIVE) setTexture(irr_driver->getTexture(m_properties[PROP_ICON]));
{ }
// Avoid warning about missing texture in case of e.g. else if (m_icon_path_type == ICON_PATH_TYPE_RELATIVE)
// screenshot widget
if(m_properties[PROP_ICON] != "")
{ {
std::string file = file_manager->getAsset(m_properties[PROP_ICON]); std::string file = file_manager->getAsset(m_properties[PROP_ICON]);
setTexture(irr_driver->getTexture(file)); setTexture(irr_driver->getTexture(file));
@ -125,7 +125,9 @@ void IconButtonWidget::add()
if (m_scale_mode == SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO) if (m_scale_mode == SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO)
{ {
useAspectRatio = (float)m_texture_w / (float)m_texture_h; assert(m_texture->getOriginalSize().Height > 0);
useAspectRatio = (float)m_texture->getOriginalSize().Width /
(float)m_texture->getOriginalSize().Height;
} }
else if (m_scale_mode == SCALE_MODE_KEEP_CUSTOM_ASPECT_RATIO) else if (m_scale_mode == SCALE_MODE_KEEP_CUSTOM_ASPECT_RATIO)
{ {

View File

@ -23,6 +23,7 @@
#include "karts/kart_properties_manager.hpp" #include "karts/kart_properties_manager.hpp"
#include "utils/log.hpp" #include "utils/log.hpp"
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"
#include "io/file_manager.hpp"
#include <IGUIEnvironment.h> #include <IGUIEnvironment.h>
#include <IGUIElement.h> #include <IGUIElement.h>
@ -37,7 +38,7 @@ using namespace irr;
KartStatsWidget::KartStatsWidget(core::recti area, const int player_id, KartStatsWidget::KartStatsWidget(core::recti area, const int player_id,
std::string kart_group, bool multiplayer, std::string kart_group, bool multiplayer,
bool display_text) : Widget(WTYPE_DIV) bool display_icons) : Widget(WTYPE_DIV)
{ {
m_title_font = !multiplayer; m_title_font = !multiplayer;
m_player_id = player_id; m_player_id = player_id;
@ -67,14 +68,13 @@ KartStatsWidget::KartStatsWidget(core::recti area, const int player_id,
default_kart.c_str()); default_kart.c_str());
} }
for (int i = 0; i < SKILL_COUNT; ++i) for (int i = 0; i < SKILL_COUNT; ++i)
{ {
irr::core::recti skillArea(0, 0, 1, 1); irr::core::recti skillArea(0, 0, 1, 1);
SkillLevelWidget* skill_bar = NULL; SkillLevelWidget* skill_bar = NULL;
skill_bar = new SkillLevelWidget(skillArea, m_player_id, multiplayer, display_text); skill_bar = new SkillLevelWidget(skillArea, m_player_id, multiplayer, display_icons);
m_skills.push_back(skill_bar); m_skills.push_back(skill_bar);
m_children.push_back(skill_bar); m_children.push_back(skill_bar);
@ -105,16 +105,19 @@ void KartStatsWidget::setValues(const KartProperties* props)
// different masses or velocities. // different masses or velocities.
m_skills[SKILL_MASS]->setValue((int) m_skills[SKILL_MASS]->setValue((int)
((kp_computed.getCombinedCharacteristic()->getMass() - 20) / 4)); ((kp_computed.getCombinedCharacteristic()->getMass() - 20) / 4));
m_skills[SKILL_MASS]->setLabel(_("WEIGHT")); m_skills[SKILL_MASS]->setIcon(irr::core::stringc(
file_manager->getAsset(FileManager::GUI, "mass.png").c_str()));
m_skills[SKILL_MASS]->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_mass", m_player_id); m_skills[SKILL_MASS]->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_mass", m_player_id);
m_skills[SKILL_SPEED]->setValue((int) m_skills[SKILL_SPEED]->setValue((int)
((kp_computed.getCombinedCharacteristic()->getEngineMaxSpeed() - 15) * 6)); ((kp_computed.getCombinedCharacteristic()->getEngineMaxSpeed() - 15) * 6));
m_skills[SKILL_SPEED]->setLabel(_("SPEED")); m_skills[SKILL_SPEED]->setIcon(irr::core::stringc(
file_manager->getAsset(FileManager::GUI, "speed.png").c_str()));
m_skills[SKILL_SPEED]->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_speed", m_player_id); m_skills[SKILL_SPEED]->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_speed", m_player_id);
m_skills[SKILL_POWER]->setValue((int)((kp_computed.getAvgPower() - 30) / 20)); m_skills[SKILL_POWER]->setValue((int)((kp_computed.getAvgPower() - 30) / 20));
m_skills[SKILL_POWER]->setLabel(_("POWER")); m_skills[SKILL_POWER]->setIcon(irr::core::stringc(
file_manager->getAsset(FileManager::GUI, "power.png").c_str()));
m_skills[SKILL_POWER]->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_power", m_player_id); m_skills[SKILL_POWER]->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_power", m_player_id);
race_manager->setDifficulty(previous_difficulty); race_manager->setDifficulty(previous_difficulty);
@ -185,11 +188,11 @@ void KartStatsWidget::setSize(const int x, const int y, const int w, const int h
m_skill_bar_y = y + h/2 - m_skill_bar_h/2; m_skill_bar_y = y + h/2 - m_skill_bar_h/2;
} // setSize } // setSize
void KartStatsWidget::setDisplayText(bool display_text) void KartStatsWidget::setDisplayIcons(bool display_icons)
{ {
for (int i = 0; i < SKILL_COUNT; ++i) for (int i = 0; i < SKILL_COUNT; ++i)
{ {
m_skills[i]->setDisplayText(display_text); m_skills[i]->setDisplayIcon(display_icons);
} }
} // setDisplayText } // setDisplayText

View File

@ -48,7 +48,9 @@ namespace GUIEngine
* if/how much space must be added to the raw label's size for the widget to be large enough */ * if/how much space must be added to the raw label's size for the widget to be large enough */
virtual int getHeightNeededAroundLabel() const { return 4; } virtual int getHeightNeededAroundLabel() const { return 4; }
/** widget coordinates */ /** widget coordinates
These are not the actual coordinates of any of the skill bars
but only (badly named) intermediate values*/
int m_skill_bar_x, m_skill_bar_y, m_skill_bar_h, m_skill_bar_w; int m_skill_bar_x, m_skill_bar_y, m_skill_bar_h, m_skill_bar_w;
int m_player_id; int m_player_id;
@ -70,7 +72,7 @@ namespace GUIEngine
KartStatsWidget(core::recti area, const int player_id, KartStatsWidget(core::recti area, const int player_id,
std::string kart_group, bool multiplayer, std::string kart_group, bool multiplayer,
bool display_text); bool display_icons);
virtual ~KartStatsWidget() {}; virtual ~KartStatsWidget() {};
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -100,8 +102,8 @@ namespace GUIEngine
/** Get the current values of the widget. */ /** Get the current values of the widget. */
int getValue(Stats type); int getValue(Stats type);
/** If the labels should be displayed. */ /** If the icons should be displayed. */
void setDisplayText(bool display_text); void setDisplayIcons(bool display_icons);
}; };
} }

View File

@ -89,10 +89,10 @@ void ModelViewWidget::clearModels()
{ {
m_models.clearWithoutDeleting(); m_models.clearWithoutDeleting();
m_model_location.clear(); m_model_location.clear();
m_model_scale.clear();
m_model_frames.clear(); m_model_frames.clear();
m_model_render_info_affected.clear(); m_model_render_info_affected.clear();
m_model_animation_speed.clear(); m_model_animation_speed.clear();
m_bone_attached.clear();
if (m_rtt_main_node != NULL) m_rtt_main_node->remove(); if (m_rtt_main_node != NULL) m_rtt_main_node->remove();
if (m_light != NULL) m_light->remove(); if (m_light != NULL) m_light->remove();
@ -106,19 +106,21 @@ void ModelViewWidget::clearModels()
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void ModelViewWidget::addModel(irr::scene::IMesh* mesh, const Vec3& location, void ModelViewWidget::addModel(irr::scene::IMesh* mesh,
const Vec3& scale, const int start_loop_frame, const core::matrix4& location,
const int start_loop_frame,
const int end_loop_frame, const int end_loop_frame,
bool all_parts_colorized, float animation_speed) bool all_parts_colorized, float animation_speed,
const std::string& bone_name)
{ {
if(!mesh) return; if(!mesh) return;
m_models.push_back(mesh); m_models.push_back(mesh);
m_model_location.push_back(location); m_model_location.push_back(location);
m_model_scale.push_back(scale);
m_model_frames.emplace_back(start_loop_frame, end_loop_frame); m_model_frames.emplace_back(start_loop_frame, end_loop_frame);
m_model_render_info_affected.push_back(all_parts_colorized); m_model_render_info_affected.push_back(all_parts_colorized);
m_model_animation_speed.push_back(animation_speed); m_model_animation_speed.push_back(animation_speed);
m_bone_attached.push_back(bone_name);
#ifndef SERVER_ONLY #ifndef SERVER_ONLY
if (!CVS->isGLSL()) if (!CVS->isGLSL())
m_render_target = NULL; m_render_target = NULL;
@ -219,59 +221,69 @@ void ModelViewWidget::setupRTTScene()
m_light = NULL; m_light = NULL;
irr_driver->clearLights(); irr_driver->clearLights();
scene::IAnimatedMeshSceneNode* animated_node = NULL;
if (m_model_frames[0].first == -1) if (m_model_frames[0].first == -1)
{ {
scene::ISceneNode* node = irr_driver->addMesh(m_models.get(0), "rtt_mesh", scene::ISceneNode* node = irr_driver->addMesh(m_models.get(0), "rtt_mesh",
NULL, m_render_info, m_model_render_info_affected[0]); NULL, m_render_info, m_model_render_info_affected[0]);
node->setPosition(m_model_location[0].toIrrVector()); node->setPosition(m_model_location[0].getTranslation());
node->setScale(m_model_scale[0].toIrrVector()); node->setRotation(m_model_location[0].getRotationDegrees());
node->setScale(m_model_location[0].getScale());
node->setMaterialFlag(video::EMF_FOG_ENABLE, false); node->setMaterialFlag(video::EMF_FOG_ENABLE, false);
m_rtt_main_node = node; m_rtt_main_node = node;
} }
else else
{ {
scene::IAnimatedMeshSceneNode* node = animated_node =
irr_driver->addAnimatedMesh((scene::IAnimatedMesh*)m_models.get(0), "rtt_mesh", irr_driver->addAnimatedMesh((scene::IAnimatedMesh*)m_models.get(0), "rtt_mesh",
NULL, m_render_info, m_model_render_info_affected[0]); NULL, m_render_info, m_model_render_info_affected[0]);
node->setPosition(m_model_location[0].toIrrVector()); animated_node->setPosition(m_model_location[0].getTranslation());
node->setFrameLoop(m_model_frames[0].first, m_model_frames[0].second); animated_node->setRotation(m_model_location[0].getRotationDegrees());
node->setAnimationSpeed(m_model_animation_speed[0]); animated_node->setScale(m_model_location[0].getScale());
node->setScale(m_model_scale[0].toIrrVector()); animated_node->setFrameLoop(m_model_frames[0].first, m_model_frames[0].second);
node->setMaterialFlag(video::EMF_FOG_ENABLE, false); animated_node->setAnimationSpeed(m_model_animation_speed[0]);
m_rtt_main_node = node; animated_node->setMaterialFlag(video::EMF_FOG_ENABLE, false);
m_rtt_main_node = animated_node;
} }
assert(m_rtt_main_node != NULL); assert(m_rtt_main_node != NULL);
assert(m_models.size() == m_model_location.size()); assert(m_models.size() == m_model_location.size());
assert(m_models.size() == m_model_frames.size()); assert(m_models.size() == m_model_frames.size());
assert(m_models.size() == m_model_scale.size());
assert(m_models.size() == m_model_render_info_affected.size()); assert(m_models.size() == m_model_render_info_affected.size());
assert(m_models.size() == m_model_animation_speed.size()); assert(m_models.size() == m_model_animation_speed.size());
assert(m_models.size() == m_bone_attached.size());
const int mesh_amount = m_models.size(); const int mesh_amount = m_models.size();
for (int n = 1; n<mesh_amount; n++) for (int n = 1; n < mesh_amount; n++)
{ {
const bool bone_attachment =
animated_node && !m_bone_attached[n].empty();
scene::ISceneNode* parent = bone_attachment ?
animated_node->getJointNode(m_bone_attached[n].c_str()) :
m_rtt_main_node;
assert(parent);
if (m_model_frames[n].first == -1) if (m_model_frames[n].first == -1)
{ {
scene::ISceneNode* node = scene::ISceneNode* node =
irr_driver->addMesh(m_models.get(n), "rtt_node", m_rtt_main_node, irr_driver->addMesh(m_models.get(n), "rtt_node", parent,
m_render_info, m_model_render_info_affected[n]); m_render_info, m_model_render_info_affected[n]);
node->setPosition(m_model_location[n].toIrrVector()); node->setPosition(m_model_location[n].getTranslation());
node->setRotation(m_model_location[n].getRotationDegrees());
node->setScale(m_model_location[n].getScale());
node->updateAbsolutePosition(); node->updateAbsolutePosition();
node->setScale(m_model_scale[n].toIrrVector());
} }
else else
{ {
scene::IAnimatedMeshSceneNode* node = scene::IAnimatedMeshSceneNode* node =
irr_driver->addAnimatedMesh((scene::IAnimatedMesh*)m_models.get(n), irr_driver->addAnimatedMesh((scene::IAnimatedMesh*)m_models.get(n),
"modelviewrtt", m_rtt_main_node, m_render_info, "modelviewrtt", parent, m_render_info,
m_model_render_info_affected[n]); m_model_render_info_affected[n]);
node->setPosition(m_model_location[n].toIrrVector()); node->setPosition(m_model_location[n].getTranslation());
node->setRotation(m_model_location[n].getRotationDegrees());
node->setScale(m_model_location[n].getScale());
node->setFrameLoop(m_model_frames[n].first, m_model_frames[n].second); node->setFrameLoop(m_model_frames[n].first, m_model_frames[n].second);
node->setAnimationSpeed(m_model_animation_speed[n]); node->setAnimationSpeed(m_model_animation_speed[n]);
node->updateAbsolutePosition(); node->updateAbsolutePosition();
node->setScale(m_model_scale[n].toIrrVector());
//Log::info("ModelViewWidget", "Set frame %d", m_model_frames[n]); //Log::info("ModelViewWidget", "Set frame %d", m_model_frames[n]);
} }
} }

View File

@ -48,11 +48,11 @@ namespace GUIEngine
float m_rotation_target; float m_rotation_target;
PtrVector<scene::IMesh, REF> m_models; PtrVector<scene::IMesh, REF> m_models;
AlignedArray<Vec3> m_model_location; std::vector<core::matrix4> m_model_location;
AlignedArray<Vec3> m_model_scale;
std::vector<std::pair<int, int> > m_model_frames; std::vector<std::pair<int, int> > m_model_frames;
std::vector<bool> m_model_render_info_affected; std::vector<bool> m_model_render_info_affected;
std::vector<float> m_model_animation_speed; std::vector<float> m_model_animation_speed;
std::vector<std::string> m_bone_attached;
std::unique_ptr<RenderTarget> m_render_target; std::unique_ptr<RenderTarget> m_render_target;
float m_angle; float m_angle;
@ -76,12 +76,12 @@ namespace GUIEngine
void add(); void add();
void clearModels(); void clearModels();
void addModel(irr::scene::IMesh* mesh, void addModel(irr::scene::IMesh* mesh,
const Vec3& location = Vec3(0,0,0), const core::matrix4& location = core::matrix4(),
const Vec3& scale = Vec3(1,1,1),
const int start_loop_frame=-1, const int start_loop_frame=-1,
const int end_loop_frame=-1, const int end_loop_frame=-1,
bool all_parts_colorized = false, bool all_parts_colorized = false,
float animation_speed=0.0f); float animation_speed = 0.0f,
const std::string& bone_name = std::string());
void update(float delta); void update(float delta);

View File

@ -24,6 +24,7 @@
#include "guiengine/widgets/model_view_widget.hpp" #include "guiengine/widgets/model_view_widget.hpp"
#include "guiengine/widgets/player_name_spinner.hpp" #include "guiengine/widgets/player_name_spinner.hpp"
#include "input/input_device.hpp" #include "input/input_device.hpp"
#include "karts/kart_model.hpp"
#include "karts/kart_properties.hpp" #include "karts/kart_properties.hpp"
#include "karts/kart_properties_manager.hpp" #include "karts/kart_properties_manager.hpp"
#include "network/network_player_profile.hpp" #include "network/network_player_profile.hpp"
@ -193,22 +194,51 @@ PlayerKartWidget::PlayerKartWidget(KartSelectionScreen* parent,
scale = 30.0f; scale = 30.0f;
} }
m_model_view->addModel( kart_model.getModel(), Vec3(0,0,0), core::matrix4 model_location;
Vec3(scale, scale, scale), model_location.setScale(core::vector3df(scale, scale, scale));
kart_model.getBaseFrame(), const bool has_win_anime =
kart_model.getBaseFrame() ); UserConfigParams::m_show_steering_animations != 0 &&
m_model_view->addModel( kart_model.getWheelModel(0), (((kart_model.getFrame(KartModel::AF_WIN_LOOP_START) > -1 ||
kart_model.getWheelGraphicsPosition(0) ); kart_model.getFrame(KartModel::AF_WIN_START) > -1) &&
m_model_view->addModel( kart_model.getWheelModel(1), kart_model.getFrame(KartModel::AF_WIN_END) > -1) ||
kart_model.getWheelGraphicsPosition(1) ); (kart_model.getFrame(KartModel::AF_SELECTION_START) > -1 &&
m_model_view->addModel( kart_model.getWheelModel(2), kart_model.getFrame(KartModel::AF_SELECTION_END) > -1));
kart_model.getWheelGraphicsPosition(2) ); m_model_view->addModel( kart_model.getModel(), model_location,
m_model_view->addModel( kart_model.getWheelModel(3), has_win_anime ?
kart_model.getWheelGraphicsPosition(3) ); kart_model.getFrame(KartModel::AF_SELECTION_START) > -1 ?
for(size_t i=0 ; i < kart_model.getSpeedWeightedObjectsCount() ; i++) kart_model.getFrame(KartModel::AF_SELECTION_START) :
kart_model.getFrame(KartModel::AF_WIN_LOOP_START) > -1 ?
kart_model.getFrame(KartModel::AF_WIN_LOOP_START) :
kart_model.getFrame(KartModel::AF_WIN_START) :
kart_model.getBaseFrame(),
has_win_anime ?
kart_model.getFrame(KartModel::AF_SELECTION_END) > -1 ?
kart_model.getFrame(KartModel::AF_SELECTION_END) :
kart_model.getFrame(KartModel::AF_WIN_END) :
kart_model.getBaseFrame(),
false/*all_parts_colorized*/,
kart_model.getAnimationSpeed());
model_location.setScale(core::vector3df(1.0f, 1.0f, 1.0f));
for (unsigned i = 0; i < 4; i++)
{ {
const SpeedWeightedObject& obj = kart_model.getSpeedWeightedObject((int)i); model_location.setTranslation(kart_model
m_model_view->addModel(obj.m_model, obj.m_position); .getWheelGraphicsPosition(i).toIrrVector());
m_model_view->addModel(kart_model.getWheelModel(i), model_location);
}
for (unsigned i = 0; i < kart_model.getSpeedWeightedObjectsCount(); i++)
{
const SpeedWeightedObject& obj = kart_model.getSpeedWeightedObject(i);
core::matrix4 swol = obj.m_location;
if (!obj.m_bone_name.empty())
{
core::matrix4 inv =
kart_model.getInverseBoneMatrix(obj.m_bone_name);
swol = inv * obj.m_location;
}
m_model_view->addModel(obj.m_model, swol, -1, -1, false, 0.0f,
obj.m_bone_name);
} }
m_model_view->setRotateContinuously( 35.0f ); m_model_view->setRotateContinuously( 35.0f );
@ -280,7 +310,7 @@ void PlayerKartWidget::setPlayerID(const int newPlayerID)
m_player_id = newPlayerID; m_player_id = newPlayerID;
if (!m_ready) if (!m_ready)
m_player_ident_spinner->setID(m_player_id); m_player_ident_spinner->setID(m_player_id);
m_kart_stats->setDisplayText(m_player_id == 0); m_kart_stats->setDisplayIcons(m_player_id == 0);
// restore previous focus, but with new player ID // restore previous focus, but with new player ID
if (focus != NULL) focus->setFocusForPlayer(m_player_id); if (focus != NULL) focus->setFocusForPlayer(m_player_id);

View File

@ -26,6 +26,7 @@
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"
#include "config/user_config.hpp" #include "config/user_config.hpp"
#include "icon_button_widget.hpp"
#include <IGUIEnvironment.h> #include <IGUIEnvironment.h>
#include <IGUIElement.h> #include <IGUIElement.h>
@ -38,12 +39,11 @@ using namespace irr;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
SkillLevelWidget::SkillLevelWidget(core::recti area, const int player_id, SkillLevelWidget::SkillLevelWidget(core::recti area, const int player_id,
bool multiplayer, bool display_text, bool multiplayer, bool display_icon,
const int value, const stringw& label) const int value)
: Widget(WTYPE_DIV) : Widget(WTYPE_DIV)
{ {
m_player_id = player_id; m_player_id = player_id;
m_display_text = display_text;
setSize(area.UpperLeftCorner.X, area.UpperLeftCorner.Y, setSize(area.UpperLeftCorner.X, area.UpperLeftCorner.Y,
area.getWidth(), area.getHeight() ); area.getWidth(), area.getHeight() );
@ -60,19 +60,22 @@ SkillLevelWidget::SkillLevelWidget(core::recti area, const int player_id,
m_bar->m_h = m_bar_h; m_bar->m_h = m_bar_h;
m_bar->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_skill_bar", m_player_id); m_bar->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_skill_bar", m_player_id);
m_label = NULL; m_iconbutton = NULL;
m_label = new LabelWidget(!multiplayer, true); m_iconbutton = new IconButtonWidget(IconButtonWidget::SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO,
m_label->setText(label,false); false, false, IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
m_label->m_x = m_label_x; //m_iconbutton_* properties are calculated in setSize method
m_label->m_y = m_label_y; m_iconbutton->m_x = m_iconbutton_x;
m_label->m_w = m_label_w; m_iconbutton->m_y = m_iconbutton_y;
m_label->m_h = m_label_h; m_iconbutton->m_w = m_iconbutton_w;
m_label->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_skill_label", m_player_id); m_iconbutton->m_h = m_iconbutton_h;
m_iconbutton->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_skill_label", m_player_id);
m_children.push_back(m_bar); m_children.push_back(m_bar);
m_children.push_back(m_label); m_children.push_back(m_iconbutton);
m_display_icon = display_icon;
} // KartStatsWidget } // KartStatsWidget
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -80,8 +83,8 @@ SkillLevelWidget::SkillLevelWidget(core::recti area, const int player_id,
void SkillLevelWidget::add() void SkillLevelWidget::add()
{ {
m_bar->add(); m_bar->add();
m_label->add(); m_iconbutton->add();
m_label->setVisible(m_display_text); m_iconbutton->setVisible(m_display_icon);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -99,12 +102,12 @@ void SkillLevelWidget::move(const int x, const int y, const int w, const int h)
m_bar_w, m_bar_w,
m_bar_h ); m_bar_h );
} }
if (m_label != NULL) if (m_iconbutton != NULL)
{ {
m_label->move(m_label_x, m_iconbutton->move( m_iconbutton_x,
m_label_y, m_iconbutton_y,
m_label_w, m_iconbutton_w,
m_label_h); m_iconbutton_h);
} }
} }
@ -117,31 +120,29 @@ void SkillLevelWidget::setSize(const int x, const int y, const int w, const int
m_w = w; m_w = w;
m_h = h; m_h = h;
int iconbox_h = h; //within icon box, icon is drawn at 75% size
int iconbox_w = h; //assuming square icon
m_iconbutton_h = iconbox_h * 3 / 4;
m_iconbutton_w = iconbox_w * 3 / 4;
// -- sizes // -- sizes
if (m_display_text) m_bar_w = m_w - iconbox_w - 25; //leaving just enough space for icon + its margin
m_bar_w = (w / 2) * 3 / 4;
else
m_bar_w = w * 2 / 3;
m_bar_h = h; m_bar_h = h;
m_label_w = w/2;
m_label_h = h;
// for shrinking effect // for shrinking effect
if (h < 175) if (h < 175)
{ {
const float factor = h / 175.0f; const float factor = h / 175.0f;
m_bar_h = (int)(m_bar_h*factor); m_bar_h = (int)(m_bar_h*factor);
m_label_h = (int)(m_label_h*factor); // no scale effect for icon (becomes too small otherwise)
} }
if (m_display_text) m_bar_x = x + iconbox_w;
m_bar_x = x + w / 2; m_bar_y = y + h/2 - m_bar_h/2; //align to midpoint in y direction
else
m_bar_x = x + w / 6;
m_bar_y = y + m_h/2 - m_bar_h/2;
m_label_x = x; m_iconbutton_x = x;
m_label_y = y + m_h/2 - m_label_h/2; m_iconbutton_y = y + h/2 - m_iconbutton_h/2; //align to midpoint in y direction
} // setSize } // setSize
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -153,18 +154,19 @@ void SkillLevelWidget::setValue(const int value)
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void SkillLevelWidget::setLabel(const irr::core::stringw& label) void SkillLevelWidget::setIcon(const irr::core::stringc& filepath)
{ {
m_label->setText(label, false); m_iconbutton->setImage(filepath.c_str());
} }
void SkillLevelWidget::setDisplayText(bool display_text) // -----------------------------------------------------------------------------
void SkillLevelWidget::setDisplayIcon(bool display_icon)
{ {
if(m_display_text != display_text) if(m_display_icon != display_icon)
{ {
m_display_text = display_text; m_display_icon = display_icon;
m_label->setVisible(display_text); m_iconbutton->setVisible(display_icon);
setSize(m_x, m_y, m_w, m_h); setSize(m_x, m_y, m_w, m_h);
} }
} }

View File

@ -26,7 +26,7 @@
#include "utils/leak_check.hpp" #include "utils/leak_check.hpp"
#include "utils/ptr_vector.hpp" #include "utils/ptr_vector.hpp"
#include "guiengine/widgets/label_widget.hpp" #include "guiengine/widgets/icon_button_widget.hpp"
#include "guiengine/widgets/progress_bar_widget.hpp" #include "guiengine/widgets/progress_bar_widget.hpp"
@ -48,22 +48,22 @@ namespace GUIEngine
/** widget coordinates */ /** widget coordinates */
int m_bar_x, m_bar_y, m_bar_h, m_bar_w; int m_bar_x, m_bar_y, m_bar_h, m_bar_w;
int m_label_x, m_label_y, m_label_h, m_label_w; int m_iconbutton_x, m_iconbutton_y, m_iconbutton_h, m_iconbutton_w;
std::string m_label_name;
int m_player_id; int m_player_id;
bool m_display_text; //shall icon be display left of the skill bar?
bool m_display_icon;
public: public:
LEAK_CHECK() LEAK_CHECK()
LabelWidget* m_label; IconButtonWidget* m_iconbutton;
ProgressBarWidget* m_bar; ProgressBarWidget* m_bar;
SkillLevelWidget(core::recti area, const int player_id, bool multiplayer, bool display_text, SkillLevelWidget(core::recti area, const int player_id,
const int value = 0, const irr::core::stringw& label = "default"); bool multiplayer, bool display_text,
const int value = 0);
virtual ~SkillLevelWidget() {}; virtual ~SkillLevelWidget() {};
@ -90,14 +90,17 @@ namespace GUIEngine
/** Change the label of the widget */ /** Change the label of the widget */
void setLabel(const irr::core::stringw& label); void setLabel(const irr::core::stringw& label);
/** Change the image for the icon. Expects an absolute file path*/
void setIcon(const irr::core::stringc& filepath);
/** Get the current label of the widget. */ /** Get the current label of the widget. */
const irr::core::stringw getLabel() const irr::core::stringw getLabel()
{ {
return m_label->getText(); return m_iconbutton->getText();
} }
/** If the label should be displayed. */ /** If the label should be displayed. */
void setDisplayText(bool display_text); void setDisplayIcon(bool display_icon);
}; };
} }

View File

@ -47,6 +47,12 @@ DeviceManager::DeviceManager()
m_multitouch_device = NULL; m_multitouch_device = NULL;
} // DeviceManager } // DeviceManager
// -----------------------------------------------------------------------------
DeviceManager::~DeviceManager()
{
delete m_multitouch_device;
} // ~DeviceManager
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
bool DeviceManager::initialize() bool DeviceManager::initialize()
{ {

View File

@ -103,6 +103,7 @@ public:
DeviceManager(); DeviceManager();
~DeviceManager();
// ---- Assign mode ---- // ---- Assign mode ----
PlayerAssignMode getAssignMode() const { return m_assign_mode; } PlayerAssignMode getAssignMode() const { return m_assign_mode; }

View File

@ -236,10 +236,7 @@ core::stringw GamepadConfig::getBindingAsString(const PlayerAction action) const
// I18N: name of stick on gamepads // I18N: name of stick on gamepads
: _("Left thumb up"); : _("Left thumb up");
// I18N: name of stick on gamepads // I18N: name of stick on gamepads
case 2: return (ad==Input::AD_POSITIVE) ? _("Left trigger") case 2: return _("Left trigger"); // I18N: name of trigger on gamepads
// I18N: name of stick on gamepads
: _("Right trigger");
// I18N: name of stick on gamepads
case 3: return (ad==Input::AD_POSITIVE) ? _("Right thumb down") case 3: return (ad==Input::AD_POSITIVE) ? _("Right thumb down")
// I18N: name of stick on gamepads // I18N: name of stick on gamepads
: _("Right thumb up"); : _("Right thumb up");
@ -248,6 +245,7 @@ core::stringw GamepadConfig::getBindingAsString(const PlayerAction action) const
// I18N: name of stick on gamepads // I18N: name of stick on gamepads
: _("Right thumb left"); : _("Right thumb left");
// I18N: name of buttons on gamepads // I18N: name of buttons on gamepads
case 5: return _("Right trigger"); // I18N: name of trigger on gamepads
case Input::HAT_H_ID: return (ad == Input::AD_POSITIVE) ? _("DPad up") case Input::HAT_H_ID: return (ad == Input::AD_POSITIVE) ? _("DPad up")
// I18N: name of buttons on gamepads // I18N: name of buttons on gamepads
: _("DPad down"); : _("DPad down");

View File

@ -33,20 +33,27 @@ GamePadDevice::GamePadDevice(const int irr_index, const std::string &name,
GamepadConfig *configuration) GamepadConfig *configuration)
{ {
m_type = DT_GAMEPAD; m_type = DT_GAMEPAD;
m_prev_axis_directions = NULL;
m_configuration = configuration; m_configuration = configuration;
GamepadConfig *config = static_cast<GamepadConfig*>(m_configuration); GamepadConfig *config = static_cast<GamepadConfig*>(m_configuration);
if(m_configuration->getNumberOfButtons()<button_count) if(m_configuration->getNumberOfButtons()<button_count)
{ {
config->setNumberOfButtons(button_count); config->setNumberOfButtons(button_count);
} }
if(m_configuration->getNumberOfAxes()<axis_count)
// HAT/POV buttons will be reported as additional axis with the values
// HAT_V_ID > HAT_H_ID. So increase the number of axis to be large
// enough to handle HAT_V/H_ID as axis number.
assert(Input::HAT_V_ID > Input::HAT_H_ID);
int adj_axis_count = axis_count > Input::HAT_V_ID ? axis_count
: Input::HAT_V_ID+1;
if(m_configuration->getNumberOfAxes()<adj_axis_count)
{ {
config->setNumberOfAxis(axis_count); config->setNumberOfAxis(adj_axis_count);
} }
m_prev_axis_directions = new Input::AxisDirection[axis_count]; m_prev_axis_directions.resize(adj_axis_count);
m_prev_axis_value = new int[axis_count]; m_prev_axis_value.resize(adj_axis_count);
m_axis_ok = new bool[axis_count]; m_axis_ok.resize(adj_axis_count);
m_irr_index = irr_index; m_irr_index = irr_index;
m_name = name; m_name = name;
@ -57,9 +64,9 @@ GamePadDevice::GamePadDevice(const int irr_index, const std::string &name,
m_axis_ok[i] = false; m_axis_ok[i] = false;
} }
m_buttonPressed = new bool[button_count]; m_button_pressed.resize(button_count);
for(int n=0; n<button_count; n++) for(int n=0; n<button_count; n++)
m_buttonPressed[n] = false; m_button_pressed[n] = false;
} // GamePadDevice } // GamePadDevice
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -67,12 +74,6 @@ GamePadDevice::GamePadDevice(const int irr_index, const std::string &name,
*/ */
GamePadDevice::~GamePadDevice() GamePadDevice::~GamePadDevice()
{ {
delete[] m_buttonPressed;
delete[] m_prev_axis_directions;
delete[] m_prev_axis_value;
delete[] m_axis_ok;
// FIXME - any need to close devices?
} // ~GamePadDevice } // ~GamePadDevice
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -93,14 +94,14 @@ int GamePadDevice::getNumberOfButtons() const
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
bool GamePadDevice::isButtonPressed(const int i) bool GamePadDevice::isButtonPressed(const int i)
{ {
return m_buttonPressed[i]; return m_button_pressed[i];
} // isButtonPressed } // isButtonPressed
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void GamePadDevice::setButtonPressed(const int i, bool isButtonPressed) void GamePadDevice::setButtonPressed(const int i, bool isButtonPressed)
{ {
m_buttonPressed[i] = isButtonPressed; m_button_pressed[i] = isButtonPressed;
} // setButtonPressed } // setButtonPressed
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -182,7 +183,7 @@ bool GamePadDevice::processAndMapInput(Input::InputType type, const int id,
} }
bool success = false; bool success = false;
if(m_prev_axis_directions == NULL) return false; // device not open if(m_prev_axis_directions.size() == 0) return false; // device not open
if (type == Input::IT_STICKMOTION) if (type == Input::IT_STICKMOTION)
{ {

View File

@ -22,6 +22,7 @@
#include "input/input_device.hpp" #include "input/input_device.hpp"
#include "utils/cpp2011.hpp" #include "utils/cpp2011.hpp"
#include <vector>
class GamepadConfig; class GamepadConfig;
/** /**
@ -31,9 +32,9 @@ class GamepadConfig;
class GamePadDevice : public InputDevice class GamePadDevice : public InputDevice
{ {
void resetAxisDirection(const int axis, Input::AxisDirection direction); void resetAxisDirection(const int axis, Input::AxisDirection direction);
bool* m_buttonPressed; std::vector<bool> m_button_pressed;
Input::AxisDirection *m_prev_axis_directions; std::vector<Input::AxisDirection> m_prev_axis_directions;
/** used to determine if an axis is valid; an axis is considered valid /** used to determine if an axis is valid; an axis is considered valid
* when at least 2 different values are read from this axis (if an axis * when at least 2 different values are read from this axis (if an axis
@ -43,10 +44,10 @@ class GamePadDevice : public InputDevice
* on linux some hard disks may be reported as gamepads with * on linux some hard disks may be reported as gamepads with
* uninteresting axis values) * uninteresting axis values)
*/ */
int *m_prev_axis_value; std::vector<int> m_prev_axis_value;
/** \see m_prev_axis_value */ /** \see m_prev_axis_value */
bool *m_axis_ok; std::vector<bool> m_axis_ok;
/** Irrlicht index of this gamepad. */ /** Irrlicht index of this gamepad. */
int m_irr_index; int m_irr_index;

View File

@ -488,11 +488,13 @@ void InputManager::inputSensing(Input::InputType type, int deviceID,
// We have to save the direction in which the axis was moved. // We have to save the direction in which the axis was moved.
// This is done by storing it as a sign (and since button can // This is done by storing it as a sign (and since button can
// be zero, we add one before changing the sign). // be zero, we add one before changing the sign).
int input_id = value>=0 ? 1+button : -(1+button); int input_button_id = value>=0 ? 1+button : -(1+button);
std::tuple<int, int> input_id(deviceID, input_button_id);
std::tuple<int, int> input_id_inv(deviceID, -input_button_id);
bool id_was_high = m_sensed_input_high_gamepad.find(input_id) bool id_was_high = m_sensed_input_high_gamepad.find(input_id)
!= m_sensed_input_high_gamepad.end(); != m_sensed_input_high_gamepad.end();
bool inverse_id_was_high = m_sensed_input_high_gamepad.find(-input_id) bool inverse_id_was_high = m_sensed_input_high_gamepad.find(input_id_inv)
!= m_sensed_input_high_gamepad.end(); != m_sensed_input_high_gamepad.end();
bool id_was_zero = m_sensed_input_zero_gamepad.find(button) bool id_was_zero = m_sensed_input_zero_gamepad.find(button)
!= m_sensed_input_zero_gamepad.end(); != m_sensed_input_zero_gamepad.end();
@ -1190,14 +1192,17 @@ EventPropagation InputManager::input(const SEvent& event)
if (button->type != BUTTON_STEERING) if (button->type != BUTTON_STEERING)
continue; continue;
float factor = UserConfigParams::m_multitouch_tilt_factor;
factor = std::max(factor, 0.1f);
if (UserConfigParams::m_multitouch_accelerometer == 1) if (UserConfigParams::m_multitouch_accelerometer == 1)
{ {
button->axis_x = (float)-event.AccelerometerEvent.X / 5.0f; button->axis_x = (float)-event.AccelerometerEvent.X / factor;
device->handleControls(button); device->handleControls(button);
} }
else if (UserConfigParams::m_multitouch_accelerometer == 2) else if (UserConfigParams::m_multitouch_accelerometer == 2)
{ {
button->axis_x = (float)event.AccelerometerEvent.Y / 5.0f; button->axis_x = (float)event.AccelerometerEvent.Y / factor;
device->handleControls(button); device->handleControls(button);
} }
} }

Some files were not shown because too many files have changed in this diff Show More