├── .gitignore
├── .idea
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── README.md
├── README.md-images
└── Screenshot_1.png
├── app
├── build.gradle
├── libs
│ └── EasyAR.jar
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ ├── aud
│ │ ├── full
│ │ │ ├── 307.jpg
│ │ │ ├── 312.jpg
│ │ │ ├── 314.jpg
│ │ │ ├── 316.jpg
│ │ │ └── 318.jpg
│ │ ├── number
│ │ │ ├── 307.jpg
│ │ │ ├── 312.jpg
│ │ │ ├── 314.jpg
│ │ │ ├── 316.jpg
│ │ │ └── 318.jpg
│ │ └── shapes
│ │ │ ├── 307.png
│ │ │ ├── 312.png
│ │ │ ├── 314.png
│ │ │ ├── 316.png
│ │ │ └── 318.png
│ ├── fonts
│ │ ├── Roboto-Bold.ttf
│ │ ├── Roboto-Italic.ttf
│ │ ├── Roboto-LightItalic.ttf
│ │ └── Roboto-Regular.ttf
│ ├── json
│ │ ├── full_sign_aud.json
│ │ ├── number_sign_aud.json
│ │ └── shapes_sign_aud.json
│ └── teachers
│ │ ├── Ананьев.jpg
│ │ ├── Андреева.jpg
│ │ ├── Боровцов.jpg
│ │ ├── Кантор.jpg
│ │ └── Крючкова.jpg
│ ├── java
│ └── com
│ │ └── khoben
│ │ └── samples
│ │ └── studyar
│ │ ├── AR
│ │ ├── AR.java
│ │ ├── ARUtils.java
│ │ ├── MyAR.java
│ │ └── Render
│ │ │ ├── GLView.java
│ │ │ ├── ImageRenderer.java
│ │ │ └── TextureHelper.java
│ │ ├── DatabaseHelper
│ │ └── FirebaseHelper.java
│ │ ├── ImageProcessing
│ │ ├── ImagePool.java
│ │ ├── ImageProcessing.java
│ │ └── ObjectPool.java
│ │ ├── Lesson.java
│ │ ├── MainActivity.java
│ │ ├── MyIterator
│ │ ├── MyContainer.java
│ │ ├── MyIterator.java
│ │ └── TargetContainer.java
│ │ └── Rubberstamp
│ │ ├── PositionCalculator.java
│ │ ├── RubberStamp.java
│ │ ├── RubberStampConfig.java
│ │ └── RubberStampPosition.java
│ ├── jniLibs
│ └── armeabi-v7a
│ │ └── libEasyAR.so
│ └── res
│ ├── drawable
│ ├── flashlight.xml
│ ├── flashlight_off.xml
│ ├── ic_search_black_24dp.xml
│ └── transition.xml
│ ├── layout
│ └── activity_main.xml
│ ├── menu
│ └── menu_main.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxxhdpi
│ └── ic_launcher.png
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── uml
├── desktop.ini
├── uml.png
└── uml.vpp
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the ART/Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | out/
15 |
16 | # Gradle files
17 | .gradle/
18 | build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 | # Android Studio Navigation editor temp files
30 | .navigation/
31 |
32 | # Android Studio captures folder
33 | captures/
34 |
35 | # IntelliJ
36 | *.iml
37 | .idea/workspace.xml
38 | .idea/tasks.xml
39 | .idea/gradle.xml
40 | .idea/dictionaries
41 | .idea/libraries
42 |
43 | # Keystore files
44 | # Uncomment the following line if you do not want to check your keystore files in.
45 | #*.jks
46 |
47 | # External native build folder generated in Android Studio 2.2 and later
48 | .externalNativeBuild
49 |
50 | # Google Services (e.g. APIs or Firebase)
51 | google-services.json
52 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
16 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | 1.8
38 |
39 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # studyAR
2 |
3 | Course project on "Augmented Reality in the educational process"
4 |
5 | ## Built With
6 |
7 | * [EasyAR 2.0](https://www.easyar.com/view/download.html) - AR engine
8 | * [OpenGL ES 2.0](https://www.khronos.org/registry/OpenGL-Refpages/es2.0/)
9 | * [RubberStamp](https://github.com/vinaygaba/RubberStamp) - Used to output text on image
10 |
11 | ## Tests
12 |
13 | 
14 |
--------------------------------------------------------------------------------
/README.md-images/Screenshot_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/README.md-images/Screenshot_1.png
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | defaultConfig {
6 | applicationId "com.khoben.samples.studyar"
7 | minSdkVersion 21
8 | targetSdkVersion 25
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | compileOptions {
20 | sourceCompatibility JavaVersion.VERSION_1_8
21 | targetCompatibility JavaVersion.VERSION_1_8
22 | }
23 | }
24 |
25 | dependencies {
26 | compile fileTree(include: ['*.jar'], dir: 'libs')
27 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
28 | exclude group: 'com.android.support', module: 'support-annotations'
29 | })
30 | compile 'com.android.support:appcompat-v7:25.4.0'
31 | compile 'com.google.firebase:firebase-database:11.8.0'
32 | testCompile 'junit:junit:4.12'
33 | }
34 |
35 |
36 | apply plugin: 'com.google.gms.google-services'
--------------------------------------------------------------------------------
/app/libs/EasyAR.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/libs/EasyAR.jar
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\android\android-sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
15 |
16 |
23 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/assets/aud/full/307.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/aud/full/307.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/aud/full/312.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/aud/full/312.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/aud/full/314.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/aud/full/314.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/aud/full/316.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/aud/full/316.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/aud/full/318.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/aud/full/318.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/aud/number/307.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/aud/number/307.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/aud/number/312.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/aud/number/312.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/aud/number/314.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/aud/number/314.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/aud/number/316.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/aud/number/316.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/aud/number/318.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/aud/number/318.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/aud/shapes/307.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/aud/shapes/307.png
--------------------------------------------------------------------------------
/app/src/main/assets/aud/shapes/312.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/aud/shapes/312.png
--------------------------------------------------------------------------------
/app/src/main/assets/aud/shapes/314.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/aud/shapes/314.png
--------------------------------------------------------------------------------
/app/src/main/assets/aud/shapes/316.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/aud/shapes/316.png
--------------------------------------------------------------------------------
/app/src/main/assets/aud/shapes/318.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/aud/shapes/318.png
--------------------------------------------------------------------------------
/app/src/main/assets/fonts/Roboto-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/fonts/Roboto-Bold.ttf
--------------------------------------------------------------------------------
/app/src/main/assets/fonts/Roboto-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/fonts/Roboto-Italic.ttf
--------------------------------------------------------------------------------
/app/src/main/assets/fonts/Roboto-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/fonts/Roboto-LightItalic.ttf
--------------------------------------------------------------------------------
/app/src/main/assets/fonts/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/fonts/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/app/src/main/assets/json/full_sign_aud.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "image": "aud/full/307.jpg",
5 | "name": "307"
6 | },
7 | {
8 | "image": "aud/full/314.jpg",
9 | "name": "314"
10 | },
11 | {
12 | "image": "aud/full/312.jpg",
13 | "name": "312"
14 | },
15 | {
16 | "image": "aud/full/316.jpg",
17 | "name": "316"
18 | },
19 | {
20 | "image": "aud/full/318.jpg",
21 | "name": "318"
22 | }
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/assets/json/number_sign_aud.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "image": "aud/number/307.jpg",
5 | "name": "307"
6 | },
7 | {
8 | "image": "aud/number/314.jpg",
9 | "name": "314"
10 | },
11 | {
12 | "image": "aud/number/312.jpg",
13 | "name": "312"
14 | },
15 | {
16 | "image": "aud/number/316.jpg",
17 | "name": "316"
18 | },
19 | {
20 | "image": "aud/number/318.jpg",
21 | "name": "318"
22 | }
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/assets/json/shapes_sign_aud.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "image": "aud/shapes/307.png",
5 | "name": "307"
6 | },
7 | {
8 | "image": "aud/shapes/312.png",
9 | "name": "312"
10 | },
11 | {
12 | "image": "aud/shapes/314.png",
13 | "name": "314"
14 | },
15 | {
16 | "image": "aud/shapes/316.png",
17 | "name": "316"
18 | },
19 | {
20 | "image": "aud/shapes/318.png",
21 | "name": "318"
22 | }
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/assets/teachers/Ананьев.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/teachers/Ананьев.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/teachers/Андреева.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/teachers/Андреева.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/teachers/Боровцов.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/teachers/Боровцов.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/teachers/Кантор.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/teachers/Кантор.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/teachers/Крючкова.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/assets/teachers/Крючкова.jpg
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/AR/AR.java:
--------------------------------------------------------------------------------
1 | package com.khoben.samples.studyar.AR;
2 |
3 | import android.opengl.GLSurfaceView;
4 |
5 | /**
6 | * Created by extless on 07.01.2018.
7 | */
8 |
9 | public interface AR {
10 | void initAR();
11 |
12 | GLSurfaceView getGLView();
13 |
14 | void setGLView(GLSurfaceView glView);
15 |
16 | boolean initialize();
17 |
18 | boolean start();
19 |
20 | boolean stop();
21 |
22 | void dispose();
23 |
24 | void initGL();
25 |
26 | void resizeGL(int w, int h);
27 |
28 | void render();
29 |
30 | boolean getFlashlightState();
31 |
32 | void toogleFlashlightState();
33 |
34 | void onResume();
35 |
36 | void onPause();
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/AR/ARUtils.java:
--------------------------------------------------------------------------------
1 | package com.khoben.samples.studyar.AR;
2 |
3 |
4 | import android.util.Log;
5 |
6 | import cn.easyar.ImageTarget;
7 | import cn.easyar.ImageTracker;
8 | import cn.easyar.StorageType;
9 |
10 |
11 | public class ARUtils {
12 | private final static String TAG = "ARUtils";
13 |
14 | public static void loadFromImage(ImageTracker tracker, String path) {
15 | ImageTarget target = new ImageTarget();
16 | String jstr = "{\n"
17 | + " \"images\" :\n"
18 | + " [\n"
19 | + " {\n"
20 | + " \"image\" : \"" + path + "\",\n"
21 | + " \"name\" : \"" + path.substring(0, path.indexOf(".")) + "\"\n"
22 | + " }\n"
23 | + " ]\n"
24 | + "}";
25 | target.setup(jstr, StorageType.Assets | StorageType.Json, "");
26 | tracker.loadTarget(target, (target1, status) -> Log.i(TAG, String.format("load target (%b): %s (%d)", status, target1.name(), target1.runtimeID())));
27 | }
28 |
29 | public static void loadFromJsonFile(ImageTracker tracker, String path, String targetname) {
30 | ImageTarget target = new ImageTarget();
31 | target.setup(path, StorageType.Assets, targetname);
32 | tracker.loadTarget(target, (target1, status) -> Log.i(TAG, String.format("load target (%b): %s (%d)", status, target1.name(), target1.runtimeID())));
33 | }
34 |
35 | public static void loadAllFromJsonFile(ImageTracker tracker, String path) {
36 | for (ImageTarget target : ImageTarget.setupAll(path, StorageType.Assets)) {
37 | tracker.loadTarget(target, (target1, status) -> Log.i(TAG, String.format("load target (%b): %s (%d)", status, target1.name(), target1.runtimeID())));
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/AR/MyAR.java:
--------------------------------------------------------------------------------
1 | //================================================================================================================================
2 | //
3 | // Copyright (c) 2015-2017 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
4 | // EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
5 | // and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
6 | //
7 | //================================================================================================================================
8 |
9 | package com.khoben.samples.studyar.AR;
10 |
11 | import java.util.ArrayList;
12 |
13 | import android.graphics.Bitmap;
14 | import android.opengl.GLES20;
15 | import android.opengl.GLSurfaceView;
16 | import android.util.Log;
17 | import android.util.Pair;
18 |
19 | import com.google.firebase.database.DataSnapshot;
20 | import com.google.firebase.database.DatabaseError;
21 | import com.google.firebase.database.ValueEventListener;
22 | import com.khoben.samples.studyar.AR.Render.GLView;
23 | import com.khoben.samples.studyar.AR.Render.ImageRenderer;
24 | import com.khoben.samples.studyar.AR.Render.TextureHelper;
25 | import com.khoben.samples.studyar.DatabaseHelper.FirebaseHelper;
26 | import com.khoben.samples.studyar.ImageProcessing.ImagePool;
27 | import com.khoben.samples.studyar.ImageProcessing.ImageProcessing;
28 | import com.khoben.samples.studyar.Lesson;
29 | import com.khoben.samples.studyar.MainActivity;
30 | import com.khoben.samples.studyar.MyIterator.MyIterator;
31 | import com.khoben.samples.studyar.MyIterator.TargetContainer;
32 |
33 | import cn.easyar.CameraCalibration;
34 | import cn.easyar.CameraDevice;
35 | import cn.easyar.CameraDeviceFocusMode;
36 | import cn.easyar.CameraDeviceType;
37 | import cn.easyar.CameraFrameStreamer;
38 | import cn.easyar.Engine;
39 | import cn.easyar.Frame;
40 | import cn.easyar.ImageTarget;
41 | import cn.easyar.ImageTracker;
42 | import cn.easyar.Renderer;
43 | import cn.easyar.Target;
44 | import cn.easyar.TargetInstance;
45 | import cn.easyar.TargetStatus;
46 | import cn.easyar.Vec2I;
47 | import cn.easyar.Vec4I;
48 |
49 |
50 | public class MyAR implements AR {
51 |
52 | private final String TAG = "MyAR";
53 |
54 | private static String key = "QjLaKui9g0HpqU2wzKEdmoCSMIrUIyh8LjZJz2JV" +
55 | "7qGXo80itvYjVzYco59Z3EVSMdGlC3OBJBgsbJ1bW4KJ0lzbAVE34SbjVz0lsEqG0ghnVuosGMnEqghEVARJzgkSsv137IphBLM21z9vVMlmoNagwCsVpejLAGy6um7PE6PRqx4Fn7oRtvQVJpu0u9ILEUqtQu2K";
56 |
57 | private CameraDevice camera;
58 | private CameraFrameStreamer streamer;
59 | private ArrayList trackers;
60 | private Renderer videobgRenderer;
61 | private ImageRenderer imageRenderer;
62 | private boolean viewportChanged;
63 | private int rotation = 0;
64 |
65 | private final Vec2I cameraResolution = new Vec2I(1280, 720);
66 | private Vec2I viewSize = new Vec2I(0, 0);
67 | private Vec4I viewport = new Vec4I(0, 0, cameraResolution.data[0], cameraResolution.data[1]);
68 |
69 | private String currentTarget;
70 | private String previusTarget;
71 |
72 | private Lesson curLesson;
73 |
74 | private String PATH_TO_MARKERS = "json/%s_sign_aud.json";
75 | private final String[] allTypes = {
76 | "shapes",
77 | "full",
78 | "number"
79 | };
80 |
81 | private Bitmap bitmap;
82 | private ImageProcessing imageProcessing;
83 | private boolean isFlashlightEnabled;
84 |
85 | private GLSurfaceView glView;
86 | private MainActivity mainActivity;
87 |
88 | private ImagePool pairObjectPool;
89 |
90 | private static volatile MyAR instance;
91 |
92 | public static MyAR getInstance(MainActivity mainActivity) {
93 | MyAR localInstance = instance;
94 | if (localInstance == null) {
95 | synchronized (MyAR.class) {
96 | localInstance = instance;
97 | if (localInstance == null) {
98 | instance = localInstance = new MyAR(mainActivity);
99 | }
100 | }
101 | }
102 | return localInstance;
103 | }
104 |
105 | private MyAR(MainActivity mainActivity) {
106 | this.mainActivity = mainActivity;
107 | glView = new GLView(mainActivity, this);
108 | trackers = new ArrayList<>();
109 | imageProcessing = new ImageProcessing(mainActivity);
110 | currentTarget = null;
111 | previusTarget = null;
112 | viewportChanged = false;
113 | isFlashlightEnabled = false;
114 | pairObjectPool = new ImagePool(mainActivity);
115 | }
116 |
117 | @Override
118 | public void initAR() {
119 | if (!Engine.initialize(mainActivity, key)) {
120 | Log.e(TAG, "Initialization Failed.");
121 | }
122 | }
123 |
124 | @Override
125 | public GLSurfaceView getGLView() {
126 | return glView;
127 | }
128 |
129 | @Override
130 | public void setGLView(GLSurfaceView glView) {
131 | this.glView = glView;
132 | }
133 |
134 | public boolean initialize() {
135 | camera = new CameraDevice();
136 | streamer = new CameraFrameStreamer();
137 | streamer.attachCamera(camera);
138 |
139 | boolean status = true;
140 | status &= camera.open(CameraDeviceType.Default);
141 | camera.setSize(cameraResolution);
142 |
143 | if (!status) {
144 | return status;
145 | }
146 |
147 | ImageTracker tracker = new ImageTracker();
148 | tracker.attachStreamer(streamer);
149 |
150 |
151 | for (String type : allTypes) {
152 | ARUtils.loadAllFromJsonFile(tracker, String.format(PATH_TO_MARKERS, type));
153 | }
154 |
155 | trackers.add(tracker);
156 |
157 | return status;
158 | }
159 |
160 | public void dispose() {
161 | for (ImageTracker tracker : trackers) {
162 | tracker.dispose();
163 | }
164 | trackers.clear();
165 | imageRenderer = null;
166 | if (videobgRenderer != null) {
167 | videobgRenderer.dispose();
168 | videobgRenderer = null;
169 | }
170 | if (streamer != null) {
171 | streamer.dispose();
172 | streamer = null;
173 | }
174 | if (camera != null) {
175 | camera.dispose();
176 | camera = null;
177 | }
178 | }
179 |
180 | public boolean start() {
181 | boolean status = true;
182 | status &= (camera != null) && camera.start();
183 | status &= (streamer != null) && streamer.start();
184 | assert camera != null;
185 | camera.setFocusMode(CameraDeviceFocusMode.Continousauto);
186 | for (ImageTracker tracker : trackers) {
187 | status &= tracker.start();
188 | }
189 | return status;
190 | }
191 |
192 | public boolean stop() {
193 | boolean status = true;
194 | for (ImageTracker tracker : trackers) {
195 | status &= tracker.stop();
196 | }
197 | status &= (streamer != null) && streamer.stop();
198 | status &= (camera != null) && camera.stop();
199 | return status;
200 | }
201 |
202 | public void initGL() {
203 | if (videobgRenderer != null) {
204 | videobgRenderer.dispose();
205 | }
206 | videobgRenderer = new Renderer();
207 | imageRenderer = new ImageRenderer();
208 | imageRenderer.init();
209 | }
210 |
211 | public void resizeGL(int width, int height) {
212 | viewSize = new Vec2I(width, height);
213 | viewportChanged = true;
214 | }
215 |
216 | private void updateViewport() {
217 | CameraCalibration calib = camera != null ? camera.cameraCalibration() : null;
218 | int rotation = calib != null ? calib.rotation() : 0;
219 | if (rotation != this.rotation) {
220 | this.rotation = rotation;
221 | viewportChanged = true;
222 | }
223 | if (viewportChanged) {
224 | Vec2I size = new Vec2I(1, 1);
225 | if ((camera != null) && camera.isOpened()) {
226 | size = camera.size();
227 | }
228 | if (rotation == 90 || rotation == 270) {
229 | size = new Vec2I(size.data[1], size.data[0]);
230 | }
231 | float scaleRatio = Math.max((float) viewSize.data[0] / (float) size.data[0], (float) viewSize.data[1] / (float) size.data[1]);
232 | Vec2I viewport_size = new Vec2I(Math.round(size.data[0] * scaleRatio), Math.round(size.data[1] * scaleRatio));
233 | viewport = new Vec4I((viewSize.data[0] - viewport_size.data[0]) / 2, (viewSize.data[1] - viewport_size.data[1]) / 2, viewport_size.data[0], viewport_size.data[1]);
234 |
235 | if ((camera != null) && camera.isOpened())
236 | viewportChanged = false;
237 | }
238 | }
239 |
240 | public void render() {
241 | GLES20.glClearColor(1.f, 1.f, 1.f, 1.f);
242 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
243 |
244 | if (videobgRenderer != null) {
245 | Vec4I default_viewport = new Vec4I(0, 0, viewSize.data[0], viewSize.data[1]);
246 | GLES20.glViewport(default_viewport.data[0], default_viewport.data[1], default_viewport.data[2], default_viewport.data[3]);
247 | if (videobgRenderer.renderErrorMessage(default_viewport)) {
248 | return;
249 | }
250 | }
251 |
252 | if (streamer == null) {
253 | return;
254 | }
255 | Frame frame = streamer.peek();
256 | try {
257 | updateViewport();
258 | GLES20.glViewport(viewport.data[0], viewport.data[1], viewport.data[2], viewport.data[3]);
259 |
260 | if (videobgRenderer != null) {
261 | videobgRenderer.render(frame, viewport);
262 | }
263 |
264 | TargetContainer targetContainer = new TargetContainer(frame.targetInstances());
265 | MyIterator targetIterator = targetContainer.getIterator();
266 |
267 | while (targetIterator.hasNext()) {
268 | TargetInstance targetInstance = (TargetInstance) targetIterator.next();
269 | int status = targetInstance.status();
270 | if (status == TargetStatus.Tracked) {
271 | Target target = targetInstance.target();
272 | ImageTarget imagetarget = target instanceof ImageTarget ? (ImageTarget) (target) : null;
273 | if (imagetarget == null) {
274 | continue;
275 | }
276 | if (imageRenderer != null) {
277 | currentTarget = imagetarget.name();
278 | if (!currentTarget.equals(previusTarget)) {
279 | Log.i(TAG, String.format("current: %s, prev: %s", currentTarget, previusTarget));
280 |
281 | Lesson existingLesson = pairObjectPool.findExistingLesson(currentTarget);
282 | if (existingLesson == null) {
283 | FirebaseHelper.timetableReference.child(currentTarget).addListenerForSingleValueEvent(new ValueEventListener() {
284 | @Override
285 | public void onDataChange(DataSnapshot dataSnapshot) {
286 |
287 | curLesson = dataSnapshot.getValue(Lesson.class);
288 | new Thread(() -> {
289 | //bitmap = imageProcessing.generateBitmap(curLesson);
290 | bitmap = pairObjectPool.checkOut(curLesson).getBitmap();
291 | TextureHelper.updateBitmap(bitmap);
292 | }).start();
293 | Log.i(TAG, curLesson.toString());
294 | }
295 |
296 | @Override
297 | public void onCancelled(DatabaseError databaseError) {
298 | Log.e(TAG, databaseError.getMessage());
299 | }
300 | });
301 | } else {
302 | bitmap = existingLesson.getBitmap();
303 | TextureHelper.updateBitmap(bitmap);
304 | }
305 | }
306 | imageRenderer.render(camera.projectionGL(0.2f, 500.f), targetInstance.poseGL(), imagetarget.size());
307 | }
308 | }
309 | previusTarget = currentTarget;
310 | }
311 |
312 | } finally {
313 | frame.dispose();
314 | }
315 | }
316 |
317 | @Override
318 | public boolean getFlashlightState() {
319 | return isFlashlightEnabled;
320 | }
321 |
322 | @Override
323 | public void toogleFlashlightState() {
324 | isFlashlightEnabled = !isFlashlightEnabled;
325 | toogleFlashlight(isFlashlightEnabled);
326 | }
327 |
328 | @Override
329 | public void onResume() {
330 | glView.onResume();
331 | }
332 |
333 | @Override
334 | public void onPause() {
335 | glView.onPause();
336 | }
337 |
338 | public void toogleFlashlight(boolean on) {
339 | camera.setFlashTorchMode(on);
340 | }
341 | }
342 |
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/AR/Render/GLView.java:
--------------------------------------------------------------------------------
1 | //================================================================================================================================
2 | //
3 | // Copyright (c) 2015-2017 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
4 | // EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
5 | // and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
6 | //
7 | //================================================================================================================================
8 |
9 | package com.khoben.samples.studyar.AR.Render;
10 |
11 | import javax.microedition.khronos.egl.EGL10;
12 | import javax.microedition.khronos.egl.EGLConfig;
13 | import javax.microedition.khronos.egl.EGLContext;
14 | import javax.microedition.khronos.egl.EGLDisplay;
15 | import javax.microedition.khronos.opengles.GL10;
16 |
17 | import android.content.Context;
18 | import android.opengl.GLSurfaceView;
19 |
20 | import com.khoben.samples.studyar.AR.AR;
21 |
22 | import cn.easyar.Engine;
23 |
24 | public class GLView extends GLSurfaceView {
25 | private AR myAR;
26 |
27 | public GLView(Context context, final AR myAR) {
28 | super(context);
29 | setEGLContextFactory(new ContextFactory());
30 | setEGLConfigChooser(new ConfigChooser());
31 |
32 | this.myAR = myAR;
33 |
34 | this.setRenderer(new GLSurfaceView.Renderer() {
35 | @Override
36 | public void onSurfaceCreated(GL10 gl, EGLConfig config) {
37 | synchronized (myAR) {
38 | myAR.initGL();
39 | }
40 | }
41 |
42 | @Override
43 | public void onSurfaceChanged(GL10 gl, int w, int h) {
44 | synchronized (myAR) {
45 | myAR.resizeGL(w, h);
46 | }
47 | }
48 |
49 | @Override
50 | public void onDrawFrame(GL10 gl) {
51 | synchronized (myAR) {
52 | myAR.render();
53 | }
54 | }
55 | });
56 | this.setZOrderMediaOverlay(true);
57 | }
58 |
59 | @Override
60 | protected void onAttachedToWindow() {
61 | super.onAttachedToWindow();
62 | synchronized (myAR) {
63 | if (myAR.initialize()) {
64 | myAR.start();
65 | }
66 | }
67 | }
68 |
69 | @Override
70 | protected void onDetachedFromWindow() {
71 | synchronized (myAR) {
72 | myAR.stop();
73 | myAR.dispose();
74 | }
75 | super.onDetachedFromWindow();
76 | }
77 |
78 | @Override
79 | public void onResume() {
80 | super.onResume();
81 | Engine.onResume();
82 | }
83 |
84 | @Override
85 | public void onPause() {
86 | Engine.onPause();
87 | super.onPause();
88 | }
89 |
90 | private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
91 | private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
92 |
93 | public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
94 | EGLContext context;
95 | int[] attrib = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE};
96 | context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib);
97 | return context;
98 | }
99 |
100 | public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
101 | egl.eglDestroyContext(display, context);
102 | }
103 | }
104 |
105 | private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
106 | public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
107 | final int EGL_OPENGL_ES2_BIT = 0x0004;
108 | final int[] attrib = {EGL10.EGL_RED_SIZE, 4, EGL10.EGL_GREEN_SIZE, 4, EGL10.EGL_BLUE_SIZE, 4,
109 | EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL10.EGL_NONE};
110 |
111 | int[] num_config = new int[1];
112 | egl.eglChooseConfig(display, attrib, null, 0, num_config);
113 |
114 | int numConfigs = num_config[0];
115 | if (numConfigs <= 0)
116 | throw new IllegalArgumentException("fail to choose EGL configs");
117 |
118 | EGLConfig[] configs = new EGLConfig[numConfigs];
119 | egl.eglChooseConfig(display, attrib, configs, numConfigs,
120 | num_config);
121 |
122 | for (EGLConfig config : configs) {
123 | int[] val = new int[1];
124 | int r = 0, g = 0, b = 0, a = 0, d = 0;
125 | if (egl.eglGetConfigAttrib(display, config, EGL10.EGL_DEPTH_SIZE, val))
126 | d = val[0];
127 | if (d < 16)
128 | continue;
129 |
130 | if (egl.eglGetConfigAttrib(display, config, EGL10.EGL_RED_SIZE, val))
131 | r = val[0];
132 | if (egl.eglGetConfigAttrib(display, config, EGL10.EGL_GREEN_SIZE, val))
133 | g = val[0];
134 | if (egl.eglGetConfigAttrib(display, config, EGL10.EGL_BLUE_SIZE, val))
135 | b = val[0];
136 | if (egl.eglGetConfigAttrib(display, config, EGL10.EGL_ALPHA_SIZE, val))
137 | a = val[0];
138 | if (r == 8 && g == 8 && b == 8 && a == 0)
139 | return config;
140 | }
141 |
142 | return configs[0];
143 | }
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/AR/Render/ImageRenderer.java:
--------------------------------------------------------------------------------
1 | //================================================================================================================================
2 | //
3 | // Copyright (c) 2015-2017 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
4 | // EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
5 | // and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
6 | //
7 | //================================================================================================================================
8 |
9 | package com.khoben.samples.studyar.AR.Render;
10 |
11 | import android.opengl.GLES20;
12 |
13 | import java.nio.ByteBuffer;
14 | import java.nio.FloatBuffer;
15 | import java.nio.ShortBuffer;
16 |
17 | import cn.easyar.Vec2F;
18 | import cn.easyar.Matrix44F;
19 |
20 | public class ImageRenderer {
21 | private int shaderProgram;
22 | private int posCoord;
23 | private int posTex;
24 | private int posTrans;
25 | private int posProj;
26 |
27 | private int vboCoord;
28 | private int vboTex;
29 | private int vboFaces;
30 |
31 | private final String TAG = "ImageRenderer";
32 |
33 | private final String vertexShaderProgram = "uniform mat4 trans;\n"
34 | + "uniform mat4 proj;\n"
35 | + "attribute vec4 coord;\n"
36 | + "attribute vec2 texcoord;\n"
37 | + "varying vec2 vtexcoord;\n"
38 | + "\n"
39 | + "void main(void)\n"
40 | + "{\n"
41 | + " vtexcoord = texcoord;\n"
42 | + " gl_Position = proj*trans*coord;\n"
43 | + "}\n"
44 | + "\n";
45 |
46 | private final String fragmentShaderProgram = "#ifdef GL_ES\n"
47 | + "precision highp float;\n"
48 | + "#endif\n"
49 | + "varying vec2 vtexcoord;\n"
50 | + "uniform sampler2D texture;\n"
51 | + "\n"
52 | + "void main(void)\n"
53 | + "{\n"
54 | + " gl_FragColor = texture2D(texture, vtexcoord);\n"
55 | + "}\n"
56 | + "\n";
57 |
58 | private float[] flatten(float[][] a) {
59 | int size = 0;
60 | for (int k = 0; k < a.length; k += 1) {
61 | size += a[k].length;
62 | }
63 | float[] l = new float[size];
64 | int offset = 0;
65 | for (int k = 0; k < a.length; k += 1) {
66 | System.arraycopy(a[k], 0, l, offset, a[k].length);
67 | offset += a[k].length;
68 | }
69 | return l;
70 | }
71 |
72 | private int[] flatten(int[][] a) {
73 | int size = 0;
74 | for (int k = 0; k < a.length; k += 1) {
75 | size += a[k].length;
76 | }
77 | int[] l = new int[size];
78 | int offset = 0;
79 | for (int k = 0; k < a.length; k += 1) {
80 | System.arraycopy(a[k], 0, l, offset, a[k].length);
81 | offset += a[k].length;
82 | }
83 | return l;
84 | }
85 |
86 | private short[] flatten(short[][] a) {
87 | int size = 0;
88 | for (int k = 0; k < a.length; k += 1) {
89 | size += a[k].length;
90 | }
91 | short[] l = new short[size];
92 | int offset = 0;
93 | for (int k = 0; k < a.length; k += 1) {
94 | System.arraycopy(a[k], 0, l, offset, a[k].length);
95 | offset += a[k].length;
96 | }
97 | return l;
98 | }
99 |
100 | private byte[] flatten(byte[][] a) {
101 | int size = 0;
102 | for (int k = 0; k < a.length; k += 1) {
103 | size += a[k].length;
104 | }
105 | byte[] l = new byte[size];
106 | int offset = 0;
107 | for (int k = 0; k < a.length; k += 1) {
108 | System.arraycopy(a[k], 0, l, offset, a[k].length);
109 | offset += a[k].length;
110 | }
111 | return l;
112 | }
113 |
114 | private byte[] byteArrayFromIntArray(int[] a) {
115 | byte[] l = new byte[a.length];
116 | for (int k = 0; k < a.length; k += 1) {
117 | l[k] = (byte) (a[k] & 0xFF);
118 | }
119 | return l;
120 | }
121 |
122 | private int generateOneBuffer() {
123 | int[] buffer = {0};
124 | GLES20.glGenBuffers(1, buffer, 0);
125 | return buffer[0];
126 | }
127 |
128 | private int generateOneTexture() {
129 | int[] buffer = {0};
130 | GLES20.glGenTextures(1, buffer, 0);
131 | return buffer[0];
132 | }
133 |
134 | public void init() {
135 | shaderProgram = GLES20.glCreateProgram();
136 | int vertShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
137 | GLES20.glShaderSource(vertShader, vertexShaderProgram);
138 | GLES20.glCompileShader(vertShader);
139 | int fragShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
140 | GLES20.glShaderSource(fragShader, fragmentShaderProgram);
141 | GLES20.glCompileShader(fragShader);
142 | GLES20.glAttachShader(shaderProgram, vertShader);
143 | GLES20.glAttachShader(shaderProgram, fragShader);
144 | GLES20.glLinkProgram(shaderProgram);
145 | GLES20.glUseProgram(shaderProgram);
146 | posCoord = GLES20.glGetAttribLocation(shaderProgram, "coord");
147 | posTex = GLES20.glGetAttribLocation(shaderProgram, "texcoord");
148 | posTrans = GLES20.glGetUniformLocation(shaderProgram, "trans");
149 | posProj = GLES20.glGetUniformLocation(shaderProgram, "proj");
150 |
151 | vboCoord = generateOneBuffer();
152 | GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboCoord);
153 | float cube_vertices[][] = {{1.0f / 2, 1.0f / 2, 0.f}, {1.0f / 2, -1.0f / 2, 0.f}, {-1.0f / 2, -1.0f / 2, 0.f}, {-1.0f / 2, 1.0f / 2, 0.f}};
154 | FloatBuffer cube_vertices_buffer = FloatBuffer.wrap(flatten(cube_vertices));
155 | GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cube_vertices_buffer.limit() * 4, cube_vertices_buffer, GLES20.GL_DYNAMIC_DRAW);
156 |
157 | vboTex = generateOneBuffer();
158 | GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboTex);
159 | int cube_vertex_colors[][] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
160 | ByteBuffer cube_vertex_colors_buffer = ByteBuffer.wrap(byteArrayFromIntArray(flatten(cube_vertex_colors)));
161 | GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cube_vertex_colors_buffer.limit(), cube_vertex_colors_buffer, GLES20.GL_STATIC_DRAW);
162 |
163 | vboFaces = generateOneBuffer();
164 | GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, vboFaces);
165 | short cube_faces[] = {3, 2, 1, 0};
166 | ShortBuffer cube_faces_buffer = ShortBuffer.wrap(cube_faces);
167 | GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, cube_faces_buffer.limit() * 2, cube_faces_buffer, GLES20.GL_STATIC_DRAW);
168 |
169 | GLES20.glUniform1i(GLES20.glGetUniformLocation(shaderProgram, "texture"), 0);
170 | TextureHelper.texture = generateOneTexture();
171 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, TextureHelper.texture);
172 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
173 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
174 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
175 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
176 | }
177 |
178 | public void render(Matrix44F projectionMatrix, Matrix44F cameraview, Vec2F size) {
179 | float size0 = size.data[0];
180 | float size1 = size.data[1];
181 |
182 | GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboCoord);
183 | float height = size0 / 1000;
184 | float cube_vertices[][] = {{size0 / 2, size1 / 2, 0}, {size0 / 2, -size1 / 2, 0}, {-size0 / 2, -size1 / 2, 0}, {-size0 / 2, size1 / 2, 0}};
185 | FloatBuffer cube_vertices_buffer = FloatBuffer.wrap(flatten(cube_vertices));
186 | GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cube_vertices_buffer.limit() * 4, cube_vertices_buffer, GLES20.GL_DYNAMIC_DRAW);
187 |
188 | GLES20.glEnable(GLES20.GL_BLEND);
189 | GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
190 | GLES20.glEnable(GLES20.GL_DEPTH_TEST);
191 | GLES20.glUseProgram(shaderProgram);
192 | GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboCoord);
193 | GLES20.glEnableVertexAttribArray(posCoord);
194 | GLES20.glVertexAttribPointer(posCoord, 3, GLES20.GL_FLOAT, false, 0, 0);
195 | GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboTex);
196 | GLES20.glEnableVertexAttribArray(posTex);
197 | GLES20.glVertexAttribPointer(posTex, 2, GLES20.GL_UNSIGNED_BYTE, false, 0, 0);
198 | GLES20.glUniformMatrix4fv(posTrans, 1, false, cameraview.data, 0);
199 | GLES20.glUniformMatrix4fv(posProj, 1, false, projectionMatrix.data, 0);
200 | GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, vboFaces);
201 |
202 | GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, vboFaces);
203 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
204 |
205 | TextureHelper.updateTexture();
206 |
207 | GLES20.glDrawElements(GLES20.GL_TRIANGLE_FAN, 4, GLES20.GL_UNSIGNED_SHORT, 0);
208 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
209 | }
210 |
211 | }
212 |
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/AR/Render/TextureHelper.java:
--------------------------------------------------------------------------------
1 | package com.khoben.samples.studyar.AR.Render;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.BitmapFactory;
6 | import android.opengl.GLES20;
7 | import android.opengl.GLUtils;
8 | import android.util.Log;
9 |
10 | import com.khoben.samples.studyar.ImageProcessing.ImageProcessing;
11 |
12 |
13 | public class TextureHelper {
14 | private static final String TAG = "TextureHelper";
15 |
16 | public static int texture;
17 | private static Bitmap curBitmap;
18 |
19 | public static int loadTexture(final Context context, final int resourceId) {
20 | final int[] textureHandle = new int[1];
21 |
22 | GLES20.glGenTextures(1, textureHandle, 0);
23 |
24 | if (textureHandle[0] == 0) {
25 | throw new RuntimeException("Error generating texture name.");
26 | }
27 |
28 | final BitmapFactory.Options options = new BitmapFactory.Options();
29 | options.inScaled = false; // No pre-scaling
30 |
31 | // Read in the resource
32 | final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
33 |
34 | // Bind to the texture in OpenGL
35 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
36 |
37 | // Set filtering
38 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
39 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
40 |
41 | // Load the bitmap into the bound texture.
42 | GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
43 |
44 | // Recycle the bitmap, since its data has been loaded into OpenGL.
45 | bitmap.recycle();
46 |
47 | return textureHandle[0];
48 | }
49 |
50 | public static int loadTexture(final Context context, final Bitmap bitmap) {
51 | final int[] textureHandle = new int[1];
52 |
53 | GLES20.glGenTextures(1, textureHandle, 0);
54 |
55 | if (textureHandle[0] == 0) {
56 | throw new RuntimeException("Error generating texture name.");
57 | }
58 |
59 | final BitmapFactory.Options options = new BitmapFactory.Options();
60 | options.inScaled = false; // No pre-scaling
61 |
62 | // Bind to the texture in OpenGL
63 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
64 |
65 | // Set filtering
66 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
67 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
68 |
69 | // Load the bitmap into the bound texture.
70 | GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
71 |
72 | // Recycle the bitmap, since its data has been loaded into OpenGL.
73 | bitmap.recycle();
74 |
75 | return textureHandle[0];
76 | }
77 |
78 | public static int loadTexture(final Context context, final String path) {
79 | final int[] textureHandle = new int[1];
80 |
81 | GLES20.glGenTextures(1, textureHandle, 0);
82 |
83 | if (textureHandle[0] == 0) {
84 | throw new RuntimeException("Error generating texture name.");
85 | }
86 |
87 | final BitmapFactory.Options options = new BitmapFactory.Options();
88 | options.inScaled = false; // No pre-scaling
89 |
90 | // Read in the resource
91 | final Bitmap bitmap = ImageProcessing.getBitmapFromAsset(context, path);
92 |
93 | // Bind to the texture in OpenGL
94 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
95 |
96 | // Set filtering
97 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
98 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
99 |
100 | // Load the bitmap into the bound texture.
101 | GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
102 |
103 | // Recycle the bitmap, since its data has been loaded into OpenGL.
104 | bitmap.recycle();
105 |
106 | return textureHandle[0];
107 | }
108 |
109 | public static void updateTexture() {
110 | Bitmap bitmap1;
111 | if (curBitmap == null) {
112 | bitmap1 = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
113 | } else
114 | bitmap1 = Bitmap.createBitmap(curBitmap);
115 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
116 | GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap1, 0);
117 | bitmap1.recycle();
118 | }
119 |
120 | public static void updateBitmap(final Bitmap bitmap){
121 | curBitmap = bitmap;
122 | }
123 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/DatabaseHelper/FirebaseHelper.java:
--------------------------------------------------------------------------------
1 | package com.khoben.samples.studyar.DatabaseHelper;
2 |
3 | import com.google.firebase.database.DatabaseReference;
4 | import com.google.firebase.database.FirebaseDatabase;
5 |
6 |
7 | public class FirebaseHelper {
8 | static public DatabaseReference timetableReference;
9 | static public DatabaseReference titleReference;
10 | static public FirebaseDatabase firebaseDatabase;
11 |
12 | public static void init() {
13 | firebaseDatabase = FirebaseDatabase.getInstance();
14 | firebaseDatabase.setPersistenceEnabled(true);
15 |
16 | titleReference = firebaseDatabase.getReference().child("title");
17 | timetableReference = firebaseDatabase.getReference().child("timetable");
18 |
19 | titleReference.keepSynced(true);
20 | timetableReference.keepSynced(true);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/ImageProcessing/ImagePool.java:
--------------------------------------------------------------------------------
1 | package com.khoben.samples.studyar.ImageProcessing;
2 |
3 | import com.khoben.samples.studyar.Lesson;
4 | import com.khoben.samples.studyar.MainActivity;
5 |
6 | import java.util.Enumeration;
7 | import java.util.Iterator;
8 |
9 |
10 | public class ImagePool extends ObjectPool {
11 |
12 | public static final String TAG = "ImagePool";
13 |
14 | private ImageProcessing imageProcessing;
15 |
16 | public ImagePool(MainActivity mainActivity) {
17 | super();
18 | imageProcessing = new ImageProcessing(mainActivity);
19 | }
20 |
21 |
22 | @Override
23 | protected Lesson create(Lesson l) {
24 | l.setBitmap(imageProcessing.generateBitmap(l));
25 | return l;
26 | }
27 |
28 | @Override
29 | public boolean validate(Lesson l) {
30 | for (Lesson l1 : unlocked.keySet()) {
31 | if (l1.getAud().equals(l.getAud())) {
32 | return true;
33 | }
34 | }
35 | return false;
36 | }
37 |
38 | public Lesson findExistingLesson(String aud) {
39 | for (Lesson l1 : unlocked.keySet()) {
40 | if (l1.getAud().equals(aud)) {
41 | return l1;
42 | }
43 | }
44 | return null;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/ImageProcessing/ImageProcessing.java:
--------------------------------------------------------------------------------
1 | package com.khoben.samples.studyar.ImageProcessing;
2 |
3 |
4 | import android.content.Context;
5 | import android.content.res.AssetManager;
6 | import android.graphics.Bitmap;
7 | import android.graphics.BitmapFactory;
8 | import android.graphics.Color;
9 | import android.graphics.Paint;
10 | import android.graphics.Rect;
11 | import android.graphics.Typeface;
12 | import android.util.Log;
13 |
14 | import com.khoben.samples.studyar.Lesson;
15 | import com.khoben.samples.studyar.MainActivity;
16 | import com.khoben.samples.studyar.Rubberstamp.RubberStamp;
17 | import com.khoben.samples.studyar.Rubberstamp.RubberStampConfig;
18 | import com.khoben.samples.studyar.Rubberstamp.RubberStampPosition;
19 |
20 |
21 | import java.io.IOException;
22 | import java.io.InputStream;
23 | import java.util.HashMap;
24 | import java.util.LinkedHashMap;
25 | import java.util.Map;
26 | import java.util.concurrent.ConcurrentHashMap;
27 | import java.util.concurrent.ConcurrentSkipListMap;
28 |
29 | public class ImageProcessing {
30 | private static final String TAG = "ImageProcessing";
31 |
32 | private Bitmap mainBitmap;
33 | private Bitmap teacherProfileBitmap;
34 | private MainActivity mainActivity;
35 | private RubberStampConfig config;
36 | private RubberStamp rubberStamp;
37 |
38 | private final static String boldFontPath = "fonts/Roboto-Bold.ttf";
39 | private final static String regularFontPath = "fonts/Roboto-Regular.ttf";
40 | private final static String italicFontPath = "fonts/Roboto-Italic.ttf";
41 | private final static String lightItalicFontPath = "fonts/Roboto-LightItalic.ttf";
42 | private final int fontSize = 100;
43 |
44 | private final int marginLeft = 30;
45 | private final int marginTop = 30;
46 |
47 | private final int scaleBitmapFactor = 4;
48 |
49 | public ImageProcessing() {
50 | }
51 |
52 | public ImageProcessing(MainActivity mainActivity) {
53 | this.mainActivity = mainActivity;
54 | rubberStamp = new RubberStamp(mainActivity);
55 | }
56 |
57 | public int getStringWidth(String s, String fontPath) {
58 | AssetManager assetManager = mainActivity.getAssets();
59 | Paint paint = new Paint();
60 | paint.setTextSize(fontSize);
61 | Typeface typeface = Typeface.createFromAsset(assetManager, fontPath);
62 | paint.setTypeface(typeface);
63 | paint.setColor(Color.BLACK);
64 | paint.setStyle(Paint.Style.FILL);
65 | Rect result = new Rect();
66 | paint.getTextBounds(s, 0, s.length(), result);
67 | return result.width();
68 | }
69 |
70 | public Bitmap generateBitmap(Lesson lesson) {
71 |
72 | if (lesson == null) {
73 | Log.w(TAG, "Lesson is NULL");
74 | return null;
75 | }
76 |
77 | Log.i(TAG, lesson.toString());
78 |
79 | Map lessonClassStringFields = new ConcurrentSkipListMap<>();
80 |
81 | lessonClassStringFields.put(String.format("Аудитория №%s", lesson.getAud()), boldFontPath);
82 | lessonClassStringFields.put(lesson.getSubject(), regularFontPath);
83 | lessonClassStringFields.put(lesson.getFio(), regularFontPath);
84 | lessonClassStringFields.put(lesson.getDegree(), lightItalicFontPath);
85 |
86 | int maxWidth = 0;
87 | int cur;
88 | for (String string : lessonClassStringFields.keySet()) {
89 | cur = getStringWidth(string, lessonClassStringFields.get(string));
90 | if (cur > maxWidth)
91 | maxWidth = cur;
92 | }
93 |
94 | teacherProfileBitmap = getBitmapFromAsset(mainActivity, String.format("teachers/%s.jpg", lesson.getFio().split(" ")[0]));
95 |
96 | if (teacherProfileBitmap == null)
97 | return null;
98 |
99 | teacherProfileBitmap = Bitmap.createScaledBitmap(teacherProfileBitmap, (teacherProfileBitmap.getWidth() * scaleBitmapFactor),
100 | (teacherProfileBitmap.getHeight() * scaleBitmapFactor), true);
101 |
102 | int amountLines = lessonClassStringFields.size();
103 |
104 | mainBitmap = Bitmap.createBitmap(maxWidth + teacherProfileBitmap.getWidth() + marginLeft * 4,
105 | fontSize * amountLines + (amountLines + 2) * marginTop, Bitmap.Config.ARGB_8888);
106 |
107 | mainBitmap.eraseColor(Color.WHITE);
108 |
109 | config = new RubberStampConfig.RubberStampConfigBuilder()
110 | .base(mainBitmap)
111 | .rubberStamp(lessonClassStringFields)
112 | .rubberStamp(teacherProfileBitmap)
113 | .rubberStampPosition(RubberStampPosition.CUSTOM, teacherProfileBitmap.getWidth() + marginLeft, fontSize)
114 | .margin(marginLeft, marginTop)
115 | .textColor(Color.BLACK)
116 | .textSize(fontSize)
117 | .textFont(regularFontPath)
118 | .build();
119 |
120 | mainBitmap = rubberStamp.addStamp(config);
121 |
122 | return mainBitmap;
123 | }
124 |
125 |
126 | public static Bitmap getBitmapFromAsset(Context context, String filePath) {
127 | AssetManager assetManager = context.getAssets();
128 |
129 | InputStream istr;
130 | Bitmap bitmap = null;
131 | try {
132 | istr = assetManager.open(filePath);
133 | bitmap = BitmapFactory.decodeStream(istr);
134 | } catch (IOException e) {
135 | Log.e(TAG, "Не удалось загрузить изображение");
136 | }
137 |
138 | return bitmap;
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/ImageProcessing/ObjectPool.java:
--------------------------------------------------------------------------------
1 | package com.khoben.samples.studyar.ImageProcessing;
2 |
3 | import java.util.Map;
4 | import java.util.concurrent.ConcurrentHashMap;
5 |
6 | public abstract class ObjectPool {
7 | protected long expirationTime;
8 |
9 | protected Map unlocked;
10 |
11 | public ObjectPool() {
12 | expirationTime = 30000; // 30 sec
13 | unlocked = new ConcurrentHashMap<>();
14 | }
15 |
16 | protected abstract T create(T l);
17 |
18 | public abstract boolean validate(T l);
19 |
20 | public synchronized T checkOut(T l) {
21 | long now = System.currentTimeMillis();
22 | T t;
23 | if (unlocked.size() > 0) {
24 | for (T t1 : unlocked.keySet()) {
25 | t = t1;
26 | if ((now - unlocked.get(t)) > expirationTime) {
27 | unlocked.remove(t);
28 | t = null;
29 | } else {
30 | if (validate(l)) {
31 | return t;
32 | } else {
33 | t = null;
34 | }
35 | }
36 | }
37 | }
38 |
39 | t = create(l);
40 | unlocked.put(t, now);
41 | return t;
42 | }
43 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/Lesson.java:
--------------------------------------------------------------------------------
1 | package com.khoben.samples.studyar;
2 |
3 |
4 | import android.graphics.Bitmap;
5 |
6 | import com.google.firebase.database.Exclude;
7 |
8 | public class Lesson {
9 |
10 | private String aud;
11 | private String subject;
12 | private String fio;
13 | private String degree;
14 |
15 |
16 | @Exclude
17 | private Bitmap bitmap;
18 |
19 | public Lesson() {
20 | }
21 |
22 | @Override
23 | public String toString() {
24 | return "Lesson{" +
25 | "aud='" + aud + '\'' +
26 | ", subject='" + subject + '\'' +
27 | ", fio='" + fio + '\'' +
28 | ", degree='" + degree + '\'' +
29 | '}';
30 | }
31 |
32 | public Lesson(String aud, String fio, String subject, String degree) {
33 | this.aud = aud;
34 | this.fio = fio;
35 | this.subject = subject;
36 | this.degree = degree;
37 | }
38 |
39 | public String getAud() {
40 | return aud;
41 | }
42 |
43 | public void setAud(String aud) {
44 | this.aud = aud;
45 | }
46 |
47 | public String getSubject() {
48 | return subject;
49 | }
50 |
51 | public void setSubject(String subject) {
52 | this.subject = subject;
53 | }
54 |
55 | public String getFio() {
56 | return fio;
57 | }
58 |
59 | public void setFio(String fio) {
60 | this.fio = fio;
61 | }
62 |
63 | public String getDegree() {
64 | return degree;
65 | }
66 |
67 | public void setDegree(String degree) {
68 | this.degree = degree;
69 | }
70 |
71 | public Bitmap getBitmap() {
72 | return bitmap;
73 | }
74 |
75 | public void setBitmap(Bitmap bitmap) {
76 | this.bitmap = bitmap;
77 | }
78 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/MainActivity.java:
--------------------------------------------------------------------------------
1 | //================================================================================================================================
2 | //
3 | // Copyright (c) 2015-2017 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
4 | // EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
5 | // and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
6 | //
7 | //================================================================================================================================
8 |
9 | package com.khoben.samples.studyar;
10 |
11 | import android.Manifest;
12 | import android.annotation.TargetApi;
13 | import android.content.pm.PackageManager;
14 | import android.opengl.GLSurfaceView;
15 | import android.os.Build;
16 | import android.os.Bundle;
17 | import android.support.annotation.NonNull;
18 | import android.support.v7.app.AppCompatActivity;
19 | import android.util.Log;
20 | import android.view.Menu;
21 | import android.view.MenuItem;
22 | import android.view.ViewGroup;
23 | import android.view.WindowManager;
24 |
25 | import com.google.firebase.database.DataSnapshot;
26 | import com.google.firebase.database.DatabaseError;
27 | import com.google.firebase.database.ValueEventListener;
28 | import com.khoben.samples.studyar.AR.AR;
29 |
30 | import java.util.HashMap;
31 |
32 | import com.khoben.samples.studyar.AR.MyAR;
33 | import com.khoben.samples.studyar.DatabaseHelper.FirebaseHelper;
34 |
35 |
36 | public class MainActivity extends AppCompatActivity {
37 | private final String TAG = "MainActivity";
38 | private GLSurfaceView glView;
39 | private AR ar;
40 |
41 | @Override
42 | protected void onCreate(Bundle savedInstanceState) {
43 | super.onCreate(savedInstanceState);
44 | setContentView(R.layout.activity_main);
45 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
46 |
47 | FirebaseHelper.init();
48 |
49 | ar = MyAR.getInstance(this);
50 | ar.initAR();
51 |
52 | glView = ar.getGLView();
53 |
54 | FirebaseHelper.titleReference.addValueEventListener(new ValueEventListener() {
55 | @Override
56 | public void onDataChange(DataSnapshot dataSnapshot) {
57 | String value = dataSnapshot.getValue(String.class);
58 | try {
59 | getSupportActionBar().setTitle(value);
60 | }
61 | catch (NullPointerException e){
62 | Log.e(TAG,e.getMessage());
63 | }
64 | }
65 |
66 | @Override
67 | public void onCancelled(DatabaseError databaseError) {
68 |
69 | }
70 | });
71 |
72 | requestCameraPermission(new PermissionCallback() {
73 | @Override
74 | public void onSuccess() {
75 | ((ViewGroup) findViewById(R.id.preview)).addView(glView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
76 | }
77 |
78 | @Override
79 | public void onFailure() {
80 | }
81 | });
82 | }
83 |
84 | private interface PermissionCallback {
85 | void onSuccess();
86 |
87 | void onFailure();
88 | }
89 |
90 | private HashMap permissionCallbacks = new HashMap();
91 | private int permissionRequestCodeSerial = 0;
92 |
93 | @TargetApi(23)
94 | private void requestCameraPermission(PermissionCallback callback) {
95 | if (Build.VERSION.SDK_INT >= 23) {
96 | if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
97 | int requestCode = permissionRequestCodeSerial;
98 | permissionRequestCodeSerial += 1;
99 | permissionCallbacks.put(requestCode, callback);
100 | requestPermissions(new String[]{Manifest.permission.CAMERA}, requestCode);
101 | } else {
102 | callback.onSuccess();
103 | }
104 | } else {
105 | callback.onSuccess();
106 | }
107 | }
108 |
109 | @Override
110 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
111 | if (permissionCallbacks.containsKey(requestCode)) {
112 | PermissionCallback callback = permissionCallbacks.get(requestCode);
113 | permissionCallbacks.remove(requestCode);
114 | boolean executed = false;
115 | for (int result : grantResults) {
116 | if (result != PackageManager.PERMISSION_GRANTED) {
117 | executed = true;
118 | callback.onFailure();
119 | }
120 | }
121 | if (!executed) {
122 | callback.onSuccess();
123 | }
124 | }
125 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
126 | }
127 |
128 | @Override
129 | protected void onResume() {
130 | super.onResume();
131 | if (glView != null) {
132 | glView.onResume();
133 | }
134 | }
135 |
136 | @Override
137 | protected void onPause() {
138 | if (glView != null) {
139 | glView.onPause();
140 | }
141 | super.onPause();
142 | }
143 |
144 | @Override
145 | public boolean onCreateOptionsMenu(Menu menu) {
146 | getMenuInflater().inflate(R.menu.menu_main, menu);
147 | return true;
148 | }
149 |
150 | @Override
151 | public boolean onOptionsItemSelected(MenuItem item) {
152 | int id = item.getItemId();
153 |
154 | switch (id) {
155 | case R.id.flashlight:
156 | ar.toogleFlashlightState();
157 |
158 | if (ar.getFlashlightState()) {
159 | item.setIcon(R.drawable.flashlight_off);
160 | } else
161 | item.setIcon(R.drawable.flashlight);
162 | return true;
163 | }
164 |
165 | return super.onOptionsItemSelected(item);
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/MyIterator/MyContainer.java:
--------------------------------------------------------------------------------
1 | package com.khoben.samples.studyar.MyIterator;
2 |
3 |
4 | import java.util.List;
5 |
6 | public interface MyContainer {
7 | MyIterator getIterator();
8 | void add(E obj);
9 | void remove(E obj);
10 | void set(List objectList);
11 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/MyIterator/MyIterator.java:
--------------------------------------------------------------------------------
1 | package com.khoben.samples.studyar.MyIterator;
2 |
3 |
4 | public interface MyIterator {
5 | boolean hasNext();
6 | E next();
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/MyIterator/TargetContainer.java:
--------------------------------------------------------------------------------
1 | package com.khoben.samples.studyar.MyIterator;
2 |
3 |
4 | import java.util.List;
5 |
6 | public class TargetContainer implements MyContainer {
7 | private List objectList;
8 |
9 | public TargetContainer(List objectList){
10 | set(objectList);
11 | }
12 |
13 | @Override
14 | public MyIterator getIterator() {
15 | return new TargetIterator();
16 | }
17 |
18 | @Override
19 | public void add(E obj) {
20 | objectList.add(obj);
21 | }
22 |
23 | @Override
24 | public void remove(E obj) {
25 | objectList.remove(obj);
26 | }
27 |
28 | @Override
29 | public void set(List objectList) {
30 | this.objectList = objectList;
31 | }
32 |
33 |
34 | private class TargetIterator implements MyIterator {
35 |
36 | private int index;
37 |
38 | @Override
39 | public boolean hasNext() {
40 |
41 | if(index < objectList.size()){
42 | return true;
43 | }
44 | return false;
45 | }
46 |
47 | @Override
48 | public E next() {
49 |
50 | if(this.hasNext()){
51 | return objectList.get(index++);
52 | }
53 | return null;
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/Rubberstamp/PositionCalculator.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2017 Vinay Gaba
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.khoben.samples.studyar.Rubberstamp;
17 |
18 | import android.util.Pair;
19 |
20 | public class PositionCalculator {
21 |
22 | /**
23 | * Utility method to calculate the coordinates of the rubberstamp based on the params passed to
24 | * it.
25 | * @param location The RubberStampPosition which denotes the position of the watermark
26 | * @param bitmapWidth The width of the bitmap where the rubberstamp will be drawn
27 | * @param bitmapHeight The height of the bitmap where the rubberstamp will be drawn
28 | * @param rubberstampWidth The width of the rubberstamp
29 | * @param rubberstampHeight The height of the rubberstamp
30 | * @return Returns a Pair object which has the x-coordinate and the y-coordinate
31 | */
32 | public static Pair getCoordinates(RubberStampPosition location,
33 | int bitmapWidth, int bitmapHeight,
34 | int rubberstampWidth, int rubberstampHeight) {
35 | switch(location){
36 | case TOP_LEFT:
37 | return new Pair<>(0, rubberstampHeight);
38 |
39 | case TOP_CENTER:
40 | return new Pair<>((bitmapWidth / 2) - (rubberstampWidth / 2),
41 | rubberstampHeight);
42 | case TOP_RIGHT:
43 | return new Pair<>(bitmapWidth - rubberstampWidth, rubberstampHeight);
44 |
45 | case CENTER_LEFT:
46 | return new Pair<>(0, (bitmapHeight / 2) + (rubberstampHeight / 2));
47 |
48 | case CENTER:
49 | return new Pair<>((bitmapWidth / 2) - (rubberstampWidth / 2),
50 | (bitmapHeight / 2) + (rubberstampHeight / 2));
51 | case CENTER_RIGHT:
52 | return new Pair<>(bitmapWidth - rubberstampWidth,
53 | (bitmapHeight / 2) + (rubberstampHeight / 2));
54 |
55 | case BOTTOM_LEFT:
56 | return new Pair<>(0, bitmapHeight);
57 |
58 | case BOTTOM_CENTER:
59 | return new Pair<>((bitmapWidth / 2) - (rubberstampWidth / 2),
60 | bitmapHeight);
61 | case BOTTOM_RIGHT:
62 | return new Pair<>(bitmapWidth - rubberstampWidth, bitmapHeight);
63 |
64 | default:
65 | return new Pair<>((bitmapWidth / 2) - (rubberstampWidth / 2),
66 | (bitmapHeight / 2) + (rubberstampHeight / 2));
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/Rubberstamp/RubberStamp.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2017 Vinay Gaba
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package com.khoben.samples.studyar.Rubberstamp;
18 |
19 | import android.content.Context;
20 | import android.graphics.Bitmap;
21 | import android.graphics.BitmapFactory;
22 | import android.graphics.BitmapShader;
23 | import android.graphics.Canvas;
24 | import android.graphics.Paint;
25 | import android.graphics.Rect;
26 | import android.graphics.Shader;
27 | import android.graphics.Typeface;
28 | import android.support.annotation.DrawableRes;
29 | import android.support.annotation.NonNull;
30 | import android.support.annotation.Nullable;
31 | import android.text.TextUtils;
32 | import android.util.Pair;
33 |
34 | import java.util.HashMap;
35 | import java.util.Map;
36 |
37 | import static com.khoben.samples.studyar.Rubberstamp.RubberStampPosition.CUSTOM;
38 | import static com.khoben.samples.studyar.Rubberstamp.RubberStampPosition.TILE;
39 |
40 |
41 | public class RubberStamp {
42 |
43 | private Context mContext;
44 | private static final int BACKGROUND_MARGIN = 10;
45 |
46 | public RubberStamp(@NonNull Context context) {
47 | mContext = context;
48 | }
49 |
50 | public Bitmap addStamp(@NonNull RubberStampConfig config) {
51 | if (config == null) {
52 | throw new IllegalArgumentException("The config passed to this method should never" +
53 | "be null");
54 | }
55 | Bitmap baseBitmap = getBaseBitmap(config);
56 | if (baseBitmap == null) {
57 | return baseBitmap;
58 | }
59 |
60 | int baseBitmapWidth = baseBitmap.getWidth();
61 | int baseBitmapHeight = baseBitmap.getHeight();
62 |
63 | Bitmap result = Bitmap.createBitmap(baseBitmapWidth, baseBitmapHeight, baseBitmap.getConfig());
64 | Canvas canvas = new Canvas(result);
65 | canvas.drawBitmap(baseBitmap, 0, 0, null);
66 |
67 | // Either one of the methods(text/bitmap) can be used to add a rubberstamp
68 | if (config.getRubberStampString() != null) {
69 | addTextToBitmap(config, canvas, baseBitmapWidth, baseBitmapHeight);
70 | }
71 | if (config.getRubberStampBitmap() != null) {
72 | addBitmapToBitmap(config.getRubberStampBitmap(), config, canvas,
73 | baseBitmapWidth, baseBitmapHeight);
74 | }
75 | return result;
76 | }
77 |
78 | @Nullable
79 | private Bitmap getBaseBitmap(@NonNull RubberStampConfig config) {
80 | Bitmap baseBitmap = config.getBaseBitmap();
81 | @DrawableRes int drawable = config.getBaseDrawable();
82 |
83 | if (baseBitmap == null) {
84 | baseBitmap = BitmapFactory.decodeResource(mContext.getResources(), drawable);
85 | if (baseBitmap == null) return null;
86 | }
87 | return baseBitmap;
88 | }
89 |
90 | /**
91 | * Method to add text RubberStamp to a canvas based on the provided configuration
92 | *
93 | * @param config The RubberStampConfig that specifies how the RubberStamp should look
94 | * @param canvas The canvas on top of which the RubberStamp needs to be drawn
95 | * @param baseBitmapWidth The width of the base bitmap
96 | * @param baseBitmapHeight The height of the base bitmap
97 | */
98 | private void addTextToBitmap(@NonNull RubberStampConfig config,
99 | @NonNull Canvas canvas,
100 | int baseBitmapWidth,
101 | int baseBitmapHeight) {
102 | Rect bounds = new Rect();
103 |
104 | Paint paint = new Paint();
105 | paint.setAntiAlias(true);
106 | paint.setUnderlineText(false);
107 |
108 | paint.setTextSize(config.getTextSize());
109 |
110 | Shader shader = config.getTextShader();
111 | // Add shader if its present in the config.
112 | if (shader != null) {
113 | paint.setShader(shader);
114 | }
115 |
116 | if (config.getTextShadowXOffset() != 0 || config.getTextShadowYOffset() != 0
117 | || config.getTextShadowBlurRadius() != 0) {
118 | // If any shadow property is present, set a shadow layer.
119 | paint.setShadowLayer(config.getTextShadowBlurRadius(),
120 | config.getTextShadowXOffset(),
121 | config.getTextShadowYOffset(),
122 | config.getTextShadowColor());
123 | }
124 |
125 | Map rubberStampString = config.getRubberStampString();
126 |
127 | int startH = 0;
128 |
129 | for (String str : config.getRubberStampString().keySet()) {
130 |
131 | Typeface typeface = Typeface.createFromAsset(mContext.getAssets(), config.getRubberStampString().get(str));
132 | paint.setTypeface(typeface);
133 |
134 | paint.getTextBounds(str, 0, str.length(), bounds);
135 |
136 | int rubberStampWidth = bounds.width();
137 | float rubberStampMeasuredWidth = paint.measureText(str);
138 | int rubberStampHeight = bounds.height();
139 |
140 | int positionX = config.getPositionX();
141 | int positionY = config.getPositionY() + startH;
142 |
143 | startH += config.getTextSize();
144 |
145 | if (config.getRubberStampPosition() != CUSTOM) {
146 | // If the specified RubberStampPosition is not CUSTOM, use calculates its x & y
147 | // co-ordinates.
148 | Pair pair = PositionCalculator
149 | .getCoordinates(config.getRubberStampPosition(),
150 | baseBitmapWidth, baseBitmapHeight,
151 | rubberStampWidth, rubberStampHeight);
152 | positionX = pair.first;
153 | positionY = pair.second;
154 | }
155 |
156 | // Add the margin to this position if it was passed to the config.
157 | positionX += config.getXMargin();
158 | positionY += config.getYMargin();
159 |
160 | float rotation = config.getRotation();
161 | // Add rotation if its present in the config.
162 | if (rotation != 0.0f) {
163 | canvas.rotate(rotation, positionX + bounds.exactCenterX(),
164 | positionY - bounds.exactCenterY());
165 | }
166 |
167 | // Add the specified text color if its present in the config or it will use the default value.
168 | paint.setColor(config.getTextColor());
169 |
170 | int alpha = config.getAplha();
171 | // Add alpha to the rubberstamp if its within range or it uses the default value.
172 | if (alpha >= 0 && alpha <= 255) {
173 | paint.setAlpha(alpha);
174 | }
175 |
176 | if (config.getRubberStampPosition() != TILE) {
177 | // The textBackgroundColor is only used if the specified RubberStampPosition is not TILE
178 | // This is because the background is actually a rectangle whose bounds are calcualted
179 | // below. In the case of TILE, we make use of a bitmap shader and there was no easy way
180 | // to draw the background rectangle for each tiled rubberstamp.
181 | int backgroundColor = config.getTextBackgroundColor();
182 | if (backgroundColor != 0) {
183 | Paint backgroundPaint = new Paint();
184 | backgroundPaint.setColor(backgroundColor);
185 | canvas.drawRect(positionX - BACKGROUND_MARGIN,
186 | positionY - bounds.height() - paint.getFontMetrics().descent - BACKGROUND_MARGIN,
187 | (positionX + rubberStampMeasuredWidth + config.getTextShadowXOffset() + BACKGROUND_MARGIN),
188 | positionY + config.getTextShadowYOffset() + paint.getFontMetrics().descent + BACKGROUND_MARGIN,
189 | backgroundPaint);
190 | }
191 | canvas.drawText(str, positionX, positionY, paint);
192 | } else {
193 | // If the specified RubberStampPosition is TILE, it tiles the rubberstamp across
194 | // the bitmap. In order to generate a tiled bitamp, it uses a bitmap shader.
195 | Bitmap textImage = Bitmap.createBitmap((int) rubberStampMeasuredWidth,
196 | rubberStampHeight,
197 | Bitmap.Config.ARGB_8888);
198 | Canvas textCanvas = new Canvas(textImage);
199 | textCanvas.drawText(str, 0, rubberStampHeight, paint);
200 | paint.setShader(new BitmapShader(textImage,
201 | Shader.TileMode.REPEAT,
202 | Shader.TileMode.REPEAT));
203 | Rect bitmapShaderRect = canvas.getClipBounds();
204 | canvas.drawRect(bitmapShaderRect, paint);
205 | }
206 |
207 | }
208 | }
209 |
210 | /**
211 | * Method to add a bitmap RubberStamp to a canvas based on the provided configuration
212 | *
213 | * @param rubberStampBitmap The bitmap which will be used as the RubberStamp
214 | * @param config The RubberStampConfig that specifies how the RubberStamp should look
215 | * @param canvas The canvas on top of which the RubberStamp needs to be drawn
216 | * @param baseBitmapWidth The width of the base bitmap
217 | * @param baseBitmapHeight The height of the base bitmap
218 | */
219 | private void addBitmapToBitmap(@NonNull Bitmap rubberStampBitmap,
220 | @NonNull RubberStampConfig config,
221 | @NonNull Canvas canvas,
222 | int baseBitmapWidth,
223 | int baseBitmapHeight) {
224 | Paint paint = new Paint();
225 | paint.setAntiAlias(true);
226 | paint.setUnderlineText(false);
227 |
228 | int alpha = config.getAplha();
229 | // Add alpha to the rubberstamp if its within range or it uses the default value.
230 | if (alpha >= 0 && alpha <= 255) {
231 | paint.setAlpha(alpha);
232 | }
233 |
234 | // int positionX = config.getPositionX();
235 | // int positionY = config.getPositionY();
236 |
237 | int positionX = 0;
238 | int positionY = 0;
239 |
240 | RubberStampPosition rubberStampPosition = config.getRubberStampPosition();
241 | if (rubberStampPosition != CUSTOM) {
242 | // If the specified RubberStampPosition is not CUSTOM, use calculates its x & y
243 | // co-ordinates.
244 | Pair pair =
245 | PositionCalculator.getCoordinates(rubberStampPosition,
246 | baseBitmapWidth, baseBitmapHeight,
247 | rubberStampBitmap.getWidth(), rubberStampBitmap.getHeight());
248 | positionX = pair.first;
249 | positionY = pair.second - rubberStampBitmap.getHeight();
250 | }
251 |
252 | // Add the margin to this position if it was passed to the config.
253 | positionX += config.getXMargin();
254 | positionY += config.getYMargin();
255 |
256 | float rotation = config.getRotation();
257 | if (rotation != 0.0f) {
258 | // Add rotation if its present in the config.
259 | canvas.rotate(rotation, positionX + (rubberStampBitmap.getWidth() / 2),
260 | positionY + (rubberStampBitmap.getHeight() / 2));
261 | }
262 |
263 | if (rubberStampPosition != TILE) {
264 | canvas.drawBitmap(rubberStampBitmap, positionX, positionY, paint);
265 | } else {
266 | // If the specified RubberStampPosition is TILE, it tiles the rubberstamp across
267 | // the bitmap. In order to generate a tiled bitamp, it uses a bitmap shader.
268 | paint.setShader(new BitmapShader(rubberStampBitmap,
269 | Shader.TileMode.REPEAT,
270 | Shader.TileMode.REPEAT));
271 | Rect bitmapShaderRect = canvas.getClipBounds();
272 | canvas.drawRect(bitmapShaderRect, paint);
273 | }
274 | }
275 | }
276 |
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/Rubberstamp/RubberStampConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2017 Vinay Gaba
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.khoben.samples.studyar.Rubberstamp;
17 |
18 | import android.graphics.Bitmap;
19 | import android.graphics.Color;
20 | import android.graphics.Shader;
21 | import android.support.annotation.ColorInt;
22 | import android.support.annotation.DrawableRes;
23 |
24 | import java.util.HashMap;
25 | import java.util.Map;
26 |
27 | import static com.khoben.samples.studyar.Rubberstamp.RubberStampPosition.CENTER;
28 |
29 |
30 | public class RubberStampConfig {
31 |
32 | private Bitmap mBaseBitmap;
33 | @DrawableRes private int mBaseDrawable;
34 | private int mTextSize;
35 | @ColorInt private int mTextColor;
36 | @ColorInt private int mTextBackgroundColor;
37 | private String mTypeFacePath;
38 | private RubberStampPosition mRubberStampPosition;
39 | private Map mRubberStampString;
40 | private Bitmap mRubberStampBitmap;
41 | private int mAplha;
42 | private Shader mTextShader;
43 | private float mRotation;
44 | private int mPositionX, mPositionY;
45 | private float mTextShadowBlurRadius, mTextShadowXOffset, mTextShadowYOffset;
46 | private int mTextShadowColor;
47 | private int mXMargin, mYMargin;
48 |
49 | private RubberStampConfig(RubberStampConfigBuilder builder) {
50 | this.mBaseBitmap = builder.mBaseBitmap;
51 | this.mBaseDrawable = builder.mBaseDrawable;
52 | this.mTextSize = builder.mTextSize;
53 | this.mTextColor = builder.mTextColor;
54 | this.mTextBackgroundColor = builder.mTextBackgroundColor;
55 | this.mTypeFacePath = builder.mTypeFacePath;
56 | this.mRubberStampPosition = builder.mRubberStampPosition;
57 | this.mRubberStampString = builder.mRubberStampString;
58 | this.mRubberStampBitmap = builder.mRubberStampBitmap;
59 | this.mAplha = builder.mAlpha;
60 | this.mTextShader = builder.mTextShader;
61 | this.mRotation = builder.mRotation;
62 | this.mPositionX = builder.mPositionX;
63 | this.mPositionY = builder.mPositionY;
64 | this.mTextShadowColor = builder.mTextShadowColor;
65 | this.mTextShadowXOffset = builder.mTextShadowXOffset;
66 | this.mTextShadowYOffset = builder.mTextShadowYOffset;
67 | this.mTextShadowBlurRadius = builder.mTextShadowBlurRadius;
68 | this.mXMargin = builder.mXMargin;
69 | this.mYMargin = builder.mYMargin;
70 | }
71 |
72 | public Bitmap getBaseBitmap() {
73 | return mBaseBitmap;
74 | }
75 |
76 | protected int getBaseDrawable() {
77 | return mBaseDrawable;
78 | }
79 |
80 | public int getTextSize() {
81 | return mTextSize;
82 | }
83 |
84 | public int getTextColor() {
85 | return mTextColor;
86 | }
87 |
88 | public int getTextBackgroundColor() {
89 | return mTextBackgroundColor;
90 | }
91 |
92 | public String getTypeFacePath() {
93 | return mTypeFacePath;
94 | }
95 |
96 | public RubberStampPosition getRubberStampPosition() {
97 | return mRubberStampPosition;
98 | }
99 |
100 | public Map getRubberStampString() {
101 | return mRubberStampString;
102 | }
103 |
104 | protected Bitmap getRubberStampBitmap() {
105 | return mRubberStampBitmap;
106 | }
107 |
108 | public int getAplha() {
109 | return mAplha;
110 | }
111 |
112 | public Shader getTextShader() {
113 | return mTextShader;
114 | }
115 |
116 | public float getRotation() {
117 | return mRotation;
118 | }
119 |
120 | public int getPositionX() {
121 | return mPositionX;
122 | }
123 |
124 | public int getPositionY() {
125 | return mPositionY;
126 | }
127 |
128 | public float getTextShadowBlurRadius() {
129 | return mTextShadowBlurRadius;
130 | }
131 |
132 | public float getTextShadowXOffset() {
133 | return mTextShadowXOffset;
134 | }
135 |
136 | public float getTextShadowYOffset() {
137 | return mTextShadowYOffset;
138 | }
139 |
140 | public int getTextShadowColor() {
141 | return mTextShadowColor;
142 | }
143 |
144 | public int getXMargin() {
145 | return mXMargin;
146 | }
147 |
148 | public int getYMargin() {
149 | return mYMargin;
150 | }
151 |
152 | public static class RubberStampConfigBuilder {
153 |
154 | private Bitmap mBaseBitmap;
155 | @DrawableRes private int mBaseDrawable;
156 | private int mTextSize = 40;
157 | @ColorInt private int mTextColor = Color.BLACK;
158 | @ColorInt private int mTextBackgroundColor;
159 | private String mTypeFacePath;
160 | private RubberStampPosition mRubberStampPosition = CENTER;
161 | private Map mRubberStampString;
162 | private Bitmap mRubberStampBitmap;
163 | private int mAlpha = 255;
164 | private Shader mTextShader;
165 | private float mRotation;
166 | private int mPositionX, mPositionY;
167 | private float mTextShadowBlurRadius, mTextShadowXOffset, mTextShadowYOffset;
168 | @ColorInt private int mTextShadowColor = Color.WHITE;
169 | private int mXMargin, mYMargin;
170 |
171 | public RubberStampConfigBuilder base(final Bitmap bitmap) {
172 | this.mBaseBitmap = bitmap;
173 | return this;
174 | }
175 |
176 | public RubberStampConfigBuilder base(@DrawableRes int drawable) {
177 | this.mBaseDrawable = drawable;
178 | return this;
179 | }
180 |
181 | public RubberStampConfigBuilder textSize(final int size) {
182 | this.mTextSize = size;
183 | return this;
184 | }
185 |
186 | public RubberStampConfigBuilder textColor(final int color) {
187 | this.mTextColor = color;
188 | return this;
189 | }
190 |
191 | public RubberStampConfigBuilder textBackgroundColor(final int color) {
192 | this.mTextBackgroundColor = color;
193 | return this;
194 | }
195 |
196 | public RubberStampConfigBuilder textFont(final String typeFacePath) {
197 | this.mTypeFacePath = typeFacePath;
198 | return this;
199 | }
200 |
201 | public RubberStampConfigBuilder rubberStampPosition(final RubberStampPosition position,
202 | final int positionX,
203 | final int positionY) {
204 | if (position != RubberStampPosition.CUSTOM) {
205 | throw new IllegalArgumentException("This constructor can only be used when the " +
206 | "rubberStampPosition is RubberStamp.CUSTOM");
207 | }
208 | this.mRubberStampPosition = position;
209 | this.mPositionX = positionX;
210 | this.mPositionY = positionY;
211 | return this;
212 | }
213 |
214 | public RubberStampConfigBuilder rubberStampPosition(final RubberStampPosition position) {
215 | this.mRubberStampPosition = position;
216 | return this;
217 | }
218 |
219 | public RubberStampConfigBuilder rubberStamp(final Map rubberStampString) {
220 | this.mRubberStampString = rubberStampString;
221 | return this;
222 | }
223 |
224 | public RubberStampConfigBuilder rubberStamp(final Bitmap rubberStampBitmap) {
225 | this.mRubberStampBitmap = rubberStampBitmap;
226 | return this;
227 | }
228 |
229 | public RubberStampConfigBuilder alpha(final int alpha) {
230 | this.mAlpha = alpha;
231 | return this;
232 | }
233 |
234 | public RubberStampConfigBuilder textShader(final Shader shader) {
235 | this.mTextShader = shader;
236 | return this;
237 | }
238 |
239 | public RubberStampConfigBuilder rotation(final float rotation) {
240 | this.mRotation = rotation;
241 | return this;
242 | }
243 |
244 | public RubberStampConfigBuilder textShadow(final float blurRadius, final float shadowXOffset,
245 | final float shadowYOffset,@ColorInt final int shadowColor) {
246 | this.mTextShadowBlurRadius = blurRadius;
247 | this.mTextShadowXOffset = shadowXOffset;
248 | this.mTextShadowYOffset = shadowYOffset;
249 | this.mTextShadowColor = shadowColor;
250 | return this;
251 | }
252 |
253 | public RubberStampConfigBuilder margin(final int xMargin, final int yMargin) {
254 | this.mXMargin = xMargin;
255 | this.mYMargin = yMargin;
256 | return this;
257 | }
258 |
259 | public RubberStampConfig build() {
260 | return new RubberStampConfig(this);
261 | }
262 | }
263 | }
264 |
--------------------------------------------------------------------------------
/app/src/main/java/com/khoben/samples/studyar/Rubberstamp/RubberStampPosition.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2017 Vinay Gaba
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.khoben.samples.studyar.Rubberstamp;
17 |
18 | /**
19 | * Enums to represent the position configurations of the rubberstamp
20 | */
21 | public enum RubberStampPosition {
22 | TOP_LEFT, TOP_RIGHT, TOP_CENTER, CENTER_LEFT, CENTER_RIGHT, CENTER, BOTTOM_LEFT, BOTTOM_RIGHT,
23 | BOTTOM_CENTER, CUSTOM, TILE
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/jniLibs/armeabi-v7a/libEasyAR.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/jniLibs/armeabi-v7a/libEasyAR.so
--------------------------------------------------------------------------------
/app/src/main/res/drawable/flashlight.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/flashlight_off.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_search_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/transition.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | studyAR
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | google()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.0.1'
10 |
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | classpath 'com.google.gms:google-services:3.1.0'
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | jcenter()
20 | google()
21 | }
22 | }
23 |
24 | task clean(type: Delete) {
25 | delete rootProject.buildDir
26 | }
27 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## Project-wide Gradle settings.
2 | #
3 | # For more details on how to configure your build environment visit
4 | # http://www.gradle.org/docs/current/userguide/build_environment.html
5 | #
6 | # Specifies the JVM arguments used for the daemon process.
7 | # The setting is particularly useful for tweaking memory settings.
8 | # Default value: -Xmx1024m -XX:MaxPermSize=256m
9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | #
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 | #Mon Dec 05 16:06:30 CST 2016
16 | org.gradle.jvmargs=-Xmx1536m
17 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Jan 11 16:12:42 GMT+07:00 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/uml/desktop.ini:
--------------------------------------------------------------------------------
1 | [LocalizedFileNames]
2 | uml.vpp=@uml,0
3 |
--------------------------------------------------------------------------------
/uml/uml.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/uml/uml.png
--------------------------------------------------------------------------------
/uml/uml.vpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoben/studyAR/7bbea7224e9c44e0ebda977844d772431b333e4d/uml/uml.vpp
--------------------------------------------------------------------------------