This commit is contained in:
Victor 2018-11-14 19:14:46 +02:00
commit b64448bee5
100 changed files with 11115 additions and 0 deletions

83
build.xml Normal file
View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<project name="S3DEditor" default="jar" basedir=".">
<description>Builds, tests, and runs the project .</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
pre-init: called before initialization of project properties
post-init: called after initialization of project properties
pre-preprocess: called before text preprocessing of sources
post-preprocess: called after text preprocessing of sources
pre-compile: called before source compilation
post-compile: called after source compilation
pre-obfuscate: called before obfuscation
post-obfuscate: called after obfuscation
pre-preverify: called before preverification
post-preverify: called after preverification
pre-jar: called before jar building
post-jar: called after jar building
pre-build: called before final distribution building
post-build: called after final distribution building
pre-clean: called before cleaning build products
post-clean: called after cleaning build products
Example of pluging a my-special-task after the compilation could look like
<target name="post-compile">
<my-special-task>
<fileset dir="${build.classes.dir}"/>
</my-special-task>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Other way how to customize the build is by overriding existing main targets.
The target of interest are:
preprocess: preprocessing
extract-libs: extraction of libraries and resources
compile: compilation
create-jad: construction of jad and jar manifest source
obfuscate: obfuscation
preverify: preverification
jar: jar archive building
run: execution
debug: execution in debug mode
build: building of the final distribution
javadoc: javadoc generation
Example of overriding the target for project execution could look like
<target name="run" depends="init,jar">
<my-special-exec jadfile="${dist.dir}/${dist.jad}"/>
</target>
Be careful about correct dependencies when overriding original target.
Again, for list of available properties which you can use check the target
you are overriding in nbproject/build-impl.xml file.
A special target for-all-configs can be used to run some specific targets for
all project configurations in a sequence. File nbproject/build-impl.xml
already contains some "for-all" targets:
jar-all
javadoc-all
clean-all
Example of definition of target iterating over all project configurations:
<target name="jar-all">
<property name="target.to.call" value="jar"/>
<antcall target="for-all-configs"/>
</target>
-->
</project>

BIN
libs/Adler32.class Normal file

Binary file not shown.

BIN
libs/Deflate$Config.class Normal file

Binary file not shown.

BIN
libs/Deflate.class Normal file

Binary file not shown.

BIN
libs/Encoder.class Normal file

Binary file not shown.

BIN
libs/Gif/a.class Normal file

Binary file not shown.

BIN
libs/Gif/b.class Normal file

Binary file not shown.

BIN
libs/Gif/c.class Normal file

Binary file not shown.

BIN
libs/JZlib.class Normal file

Binary file not shown.

BIN
libs/JpegEncoder$DCT.class Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
libs/JpegEncoder.class Normal file

Binary file not shown.

BIN
libs/Lib_gif.class Normal file

Binary file not shown.

BIN
libs/Lib_jpeg.class Normal file

Binary file not shown.

BIN
libs/Lib_png3.class Normal file

Binary file not shown.

BIN
libs/StaticTree.class Normal file

Binary file not shown.

BIN
libs/Tree.class Normal file

Binary file not shown.

BIN
libs/ZStream.class Normal file

Binary file not shown.

1250
nbproject/build-impl.xml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
build.xml.data.CRC32=e04156cc
build.xml.script.CRC32=871132c0
build.xml.stylesheet.CRC32=9c6a911d
nbproject/build-impl.xml.data.CRC32=e04156cc
nbproject/build-impl.xml.script.CRC32=44247065
nbproject/build-impl.xml.stylesheet.CRC32=051c3749

View File

@ -0,0 +1,8 @@
#Mon, 21 Oct 2013 10:01:29 +0300
app-version.autoincrement=true
config.active=
deployment.counter=4
deployment.number=0.0.3
javadoc.preview=true
netbeans.user=C\:\\Users\\aNNiMON\\AppData\\Roaming\\NetBeans\\dev
platform.apis.defaults=JSR179-1.0,JSR75-1.0

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group/>
</open-files>
</project-private>

View File

@ -0,0 +1,106 @@
abilities=MMAPI=1.0,CLDC=1.1,OBEX=1.0,JSR179=1.0,bin/api__.jar=1.0,JSR82=1.0,JSR184=1.0,NOKIAUI=1.0,WMA=1.1,libs/jsr75.jar=1.0,MIDP=2.0,JSR75=1.0,JSR172=1.0,
all.configurations=\
application.args=
application.description=
application.description.detail=
application.name=
application.vendor=Vendor
build.classes.dir=${build.dir}/compiled
build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient,**/*.vmd
build.dir=build/${config.active}
build.root.dir=build
debug.level=debug
debugger.timeout=
deployment.copy.target=deploy
deployment.instance=default
deployment.jarurl=${dist.jar}
deployment.method=NONE
deployment.override.jarurl=false
dist.dir=dist/${config.active}
dist.jad=S3DEditor.jad
dist.jar=S3DEditor.jar
dist.javadoc.dir=${dist.dir}/doc
dist.root.dir=dist
extra.classpath=
file.reference.S3DEditor-libs=libs
filter.exclude.tests=false
filter.excludes=
filter.more.excludes=**/overview.html,**/package.html
filter.use.standard=true
jar.compress=true
javac.debug=true
javac.deprecation=false
javac.encoding=UTF-8
javac.optimize=false
javac.source=1.3
javac.target=1.3
javadoc.author=false
javadoc.encoding=
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
libs.classpath=${file.reference.S3DEditor-libs}
main.class=
main.class.class=applet
manifest.apipermissions=
manifest.file=manifest.mf
manifest.is.liblet=false
manifest.jad=
manifest.manifest=
manifest.midlets=MIDlet-1: Shaman,/icon.png,Main\n
manifest.others=MIDlet-Vendor: Shaman\nMIDlet-Name: S3DEditor\nMIDlet-Version: 1.0\n
manifest.pushregistry=
name=S3DEditor
no.dependencies=false
nokiaS80.application.icon=
obfuscated.classes.dir=${build.dir}/obfuscated
obfuscation.custom=
obfuscation.level=0
obfuscator.destjar=${build.dir}/obfuscated.jar
obfuscator.srcjar=${build.dir}/before-obfuscation.jar
platform.active=Oracle_Java_TM__Platform_Micro_Edition_SDK_3_2
platform.active.description=CLDC Oracle Java(TM) Platform Micro Edition SDK 3.2
platform.apis=JSR75-1.0,JSR179-1.0
platform.bootclasspath=${platform.home}/lib/jsr75_1.0.jar:${platform.home}/lib/jsr179_1.0.jar:${platform.home}/lib/midp_2.0.jar:${platform.home}/lib/cldc_1.1.jar
platform.configuration=CLDC-1.1
platform.device=JavaMEPhone2
platform.fat.jar=true
platform.profile=MIDP-2.0
platform.trigger=CLDC
platform.type=UEI-1.0.1
preprocessed.dir=${build.dir}/preprocessed
preverify.classes.dir=${build.dir}/preverified
preverify.sources.dir=${build.dir}/preverifysrc
resources.dir=resources
run.cmd.options=
run.jvmargs=
run.method=STANDARD
run.security.domain=trusted
run.use.security.domain=false
savaje.application.icon=
savaje.application.icon.focused=
savaje.application.icon.small=
savaje.application.uid=TBD
savaje.bundle.base=
savaje.bundle.debug=false
savaje.bundle.debug.port=
semc.application.caps=
semc.application.icon=
semc.application.icon.count=
semc.application.icon.splash=
semc.application.icon.splash.installonly=false
semc.application.uid=E0055103
semc.certificate.path=
semc.private.key.password=
semc.private.key.path=
sign.alias=
sign.enabled=false
sign.keystore=
src.dir=src
use.emptyapis=true
use.preprocessor=true

10
nbproject/project.xml Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.kjava.j2meproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2me-project">
<name>S3DEditor</name>
<minimum-ant-version>1.6</minimum-ant-version>
</data>
</configuration>
</project>

492
src/Color.java Normal file
View File

@ -0,0 +1,492 @@
/*
* Экран выбора цвета.
*/
/*
* To change this template, choose Tools | Templates and open the template in
* the editor.
*/
import javax.microedition.lcdui.*;
/**
* @author Shaman
*/
public class Color extends Canvas{
int ww,hh,in,k,mode=0,sh; // ширина, высота экрана, текущий редактируемый элемент, клавиатура, текущее окно, и что-то еще
static int r=0xff,gr=0xff,b=0xff;
public static int x,y,frame;
private float h, s, v;
public static float H = 0;
private int[] data;
private int[] colordata;
private float dh, ds, dv;
private int offset = 3;
// private Image buf;
// private Graphics p;
/**
* constructor
*/
public Color() {
setFullScreenMode(true);
ww=getWidth();
hh=getHeight();
//buf=Image.createImage(ww, hh);
//p=buf.getGraphics();
dh = 360.0f / (float) (ww - 6);
ds = 255.0f / 128.0f;
dv = 255.0f / 128.0f;
colordata = new int[128 * 128];
sh=Statics.font.getHeight();
}
/**
* paint
*/
public void paint(Graphics g) {
g.setFont(Statics.font);
if(frame==0){
g.setColor(Statics.menuBack);
g.fillRect(0, 0, ww,hh);
g.setColor(0xff0000);
g.fillRect(5, sh+5, r*(ww/2)/255, 20);
g.setColor(0x00ff00);
g.fillRect(15, sh+30, gr*(ww/2)/255, 20);
g.setColor(0xff);
g.fillRect(25, sh+55, b*(ww/2)/255, 20);
g.setColor(r,gr,b);
g.fillRect(5, sh+90, (ww-10), 25);
if(in==0)g.setColor(0xffaaaa); else g.setColor(0x677667);
g.drawRect(5, sh+5, r*(ww/2)/255, 20);
if(in==1)g.setColor(0xffaaaa); else g.setColor(0x677667);
g.drawRect(15, sh+30, gr*(ww/2)/255, 20);
if(in==2)g.setColor(0xffaaaa); else g.setColor(0x677667);
g.drawRect(25, sh+55, b*(ww/2)/255, 20);
g.setColor(0x677667);
g.drawRect(5, sh+90, (ww-10), 25);
g.setColor(Statics.textColor);
g.drawString(""+r, ww/2+15, sh+5, 20);
g.drawString(""+gr, ww/2+25, sh+30, 20);
g.drawString(""+b, ww/2+35, sh+55, 20);}
else if(frame==1){
//g.setColor(0xffff00);
//g.drawRect(0, 0, ww - 1, hh - 1);
if(x>=128)x=127;
if(y>=128)y=127;
if(x<0)x=0;
if(y<0)y=0;
g.setColor(Statics.menuBack);
g.fillRect(0, 0, ww, hh);
//hsvline
h = 0;
for (int i = 0; i < ww - 6; i++) {
data = HSVtoRGB((int) h, 255, 255);
h += dh;
if(Math.abs(Math.floor(H)-Math.floor(h))<=1)
g.setColor(255-data[0],255-data[1],255-data[2]);
else
g.setColor(data[0], data[1], data[2]);
g.drawLine(offset + i, sh+6, offset + i, sh+24);
}
if(in<1){
upData();
}
if(in==0)g.setColor(0xffaaaa); else g.setColor(0x677667);
g.drawRect(2, sh+5, ww - 5, 20);
if(in==1)g.setColor(0xffaaaa); else g.setColor(0x677667);
g.drawRect(15, sh+38, 129, 129);
g.drawRGB(colordata, 0, 128, 16, sh+39, 128, 128, false);
g.setColor(colordata[y*128+x]);
g.fillRect(144, sh+39, 20, 128);
g.setColor(0x555555);
g.drawArc(x+9, y+sh+32, 15, 15, 0, 360);
//g.drawString("" + (int)H, ww/2, sh+39, 20);
}
drawLeftSoft(g,frame==0?(Statics.russian?"Палитра":"Palette"):"RGB");
drawRightSoft(g,"Ok");
repaint();
if(k!=0){
sk();
}
}
private void upData(){
// обновляем HSV-квадрат
v = 255;
for (int i = 0; i < 128; i++) {
s = 255;
for (int i2 = 0; i2 < 128; i2++) {
data = HSVtoRGB((int) H, (int) s, (int) v);
colordata[(i * 128) + i2] = data[0] << 16 | data[1] << 8 | data[2];
s -= ds;
}
v -= dv;
}
}
private void drawLeftSoft(Graphics g,String s){
if(!Statics.touch){
g.setColor(8947967);
g.fillRoundRect(0, hh - sh+1, g.getFont().stringWidth(s)+5, sh-1,10,10);
g.setColor(0);
g.drawRoundRect(0, hh - sh+1, g.getFont().stringWidth(s)+5, sh-2,10,10);
g.setColor(0x555555);
g.drawString(s, 2, hh - 2, 36);
g.setColor(Statics.textColor);
g.drawString(s, 3, hh - 1, 36);}
else{
g.setColor(8947967);
g.fillRoundRect(0, hh - 40, g.getFont().stringWidth(s)+5, 39,15,15);
g.setColor(0);
g.drawRoundRect(0, hh - 40, g.getFont().stringWidth(s)+5, 38,15,15);
g.setColor(0x555555);
g.drawString(s, 2, hh + sh/2 - 20, 36);
g.setColor(Statics.textColor);
g.drawString(s, 3, hh +sh/2 - 19, 36);
}
}
private void drawRightSoft(Graphics g,String s){
if(!Statics.touch){
g.setColor(8947967);
g.fillRoundRect(ww-g.getFont().stringWidth(s)-5, hh - sh + 1, g.getFont().stringWidth(s)+5, sh-1,10,10);
g.setColor(0);
g.drawRoundRect(ww-g.getFont().stringWidth(s)-5, hh - sh + 1, g.getFont().stringWidth(s)+4, sh-2,10,10);
g.setColor(0x555555);
g.drawString(s, ww - 4, hh - 2, 40);
g.setColor(Statics.textColor);
g.drawString(s, ww - 3, hh - 1, 40);}
else{
g.setColor(8947967);
g.fillRoundRect(ww-g.getFont().stringWidth(s)-5, hh - 40, g.getFont().stringWidth(s)+5, 39,15,15);
g.setColor(0);
g.drawRoundRect(ww-g.getFont().stringWidth(s)-5, hh-40, g.getFont().stringWidth(s)+4, 38,15,15);
g.setColor(0x555555);
g.drawString(s, ww - 4, hh+sh/2- 20, 40);
g.setColor(Statics.textColor);
g.drawString(s, ww - 3, hh+sh/2 - 19, 40);
}
}
public static int[] HSVtoRGB(int H, int S, int V) {
int divisor = 255 * 60;
int f;
int hTemp;
int p, q, t;
int VS;
if (S == 0) {
return new int[]{V, V, V};
} else {
if (H == 360) {
hTemp = 0;
} else {
hTemp = H;
}
f = hTemp % 60;
hTemp = hTemp / 60;
VS = V * S;
p = V - VS / 255;
q = V - (VS * f) / divisor;
t = V - (VS * (60 - f)) / divisor;
if (hTemp == 0) {
return new int[]{V, t, p};
} else if (hTemp == 1) {
return new int[]{q, V, p};
} else if (hTemp == 2) {
return new int[]{p, V, t};
} else if (hTemp == 3) {
return new int[]{p, q, V};
} else if (hTemp == 4) {
return new int[]{t, p, V};
} else if (hTemp == 5) {
return new int[]{V, p, q};
} else {
return new int[]{0, 0, 0};
}
}
}
public static float[] RGBtoHSV(float rr,float gg,float bb){
float computedH,computedS,computedV;
rr=rr/255; gg=gg/255; bb=bb/255;
float minRGB = Math.min(rr,Math.min(gg,bb));
float maxRGB = Math.max(rr,Math.max(gg,bb));
// Black-gray-white
if (minRGB==maxRGB) {
computedV = minRGB*255;
return new float[]{0,255,255-computedV};
}
// Colors other than black-gray-white:
float dd = (rr==minRGB) ? gg-bb : ((bb==minRGB) ? rr-gg : bb-rr);
float hh = (rr==minRGB) ? 3 : ((bb==minRGB) ? 1 : 5);
computedH = 60*(hh - dd/(maxRGB - minRGB));
computedS = 255*(maxRGB - minRGB)/maxRGB;
computedV = maxRGB*255;
return new float[]{computedH,255-computedS,255-computedV};
}
private void sk(){
// обработка клавиш
int sp=1;
int gac=getGameAction(k);
switch(gac){
case LEFT: if(frame==0){
if(in==0&&r>=sp)
r-=sp;
else if(in==1&&gr>=sp)
gr-=sp;
else if(in==2&&b>=sp)
b-=sp;
}
else{
if(in==0){
if((H-=5)<0)
H=360;}
else if(in==1){if(x>=1)x-=1;}
} break;
case RIGHT: if(frame==0){
if(in==0&&r<=254)
r+=sp;
else if(in==1&&gr<=254)
gr+=sp;
else if(in==2&&b<=254)
b+=sp;}
else {
if(in==0){
if((H+=5)>360)
H=0;}
else if(in==1){if(x<127)x+=1;}
}break;}
switch(k){
case 56: if(in==1&&frame==1){
if(y<127)y+=1;
}break;
case 50: if(in==1&&frame==1){
if(y>=1)y-=1;
}
}
}
public void setColor(int c){
r=c>>16&0xff;
gr=c>>8&0xff;
b=c&0xff;
if(frame==1){
float[] data=RGBtoHSV(r,gr,b); H=data[0]; x=(int)(data[1]*128/255); y=(int)(data[2]*128/255); upData();
}
}
/**
* Called when a key is pressed.
*/
protected void keyPressed(int key) {
if((key==50||key==56||key==52||key==54)&&frame==1&&in==1)k=key;
int sp=5;
String strCode = null;
try {
strCode = getKeyName(key).toLowerCase();
}
catch (IllegalArgumentException e) {
}
if (strCode != null)
{
if (((("soft1".equals(strCode)) || ("soft 1".equals(strCode)) || ("soft_1".equals(strCode)) || ("softkey 1".equals(strCode)) || ("sk2(left)".equals(strCode)) || (strCode.startsWith("left soft"))))){
if(frame==0){frame=1; float[] data=RGBtoHSV(r,gr,b); H=data[0]; x=(int)(data[1]*128/255); y=(int)(data[2]*128/255); upData(); } else{ frame=0; setColor(colordata[y*128+x]); } in=0; return;} //left
if (("soft2".equals(strCode)) || ("soft 2".equals(strCode)) || ("soft_2".equals(strCode)) || ("softkey 4".equals(strCode)) || ("sk1(right)".equals(strCode)) || (strCode.startsWith("right soft"))){
returnColor(); return;}//right
}
switch (key)
{
case -202:
case -21:
case -6:
case 21:
case 105:
case 113:
case 57345:
if(frame==0){frame=1; float[] data=RGBtoHSV(r,gr,b); H=data[0]; x=(int)(data[1]*128/255); y=(int)(data[2]*128/255); upData(); } else{ frame=0; setColor(colordata[y*128+x]); } in=0; break;//left
case -203:
case -22:
case -7:
case 22:
case 106:
case 112:
case 57346:
returnColor();break;//right
}
int ga=getGameAction(key);
switch(ga){
case LEFT: if(in==-1&&frame==1){frame=0;break;}if(frame==0){
if(in==0&&r>=sp)
r-=sp;
else if(in==1&&gr>=sp)
gr-=sp;
else if(in==2&&b>=sp)
b-=sp;
}
else{
if(in==0){
if((H-=sp)<0)
H=360;}
else if(in==1){}
} break;
case RIGHT: if(in==-1&&frame==0){frame=1;break;}
if(frame==0){
if(in==0&&r<=254)
r+=sp;
else if(in==1&&gr<=254)
gr+=sp;
else if(in==2&&b<=254)
b+=sp;}
else {
if(in==0){
if((H+=sp)>360)
H=0;}
else if(in==1){}
} break;
case UP: if (in>0&&key!=50)in--;break;
case DOWN: if(in<2&&key!=56)in++;if(frame==1&&in>1)in=1;break;
case FIRE: returnColor();
}
if(key==49){frame=0; setColor(colordata[y*128+x]); in=0; }
else if(key==51){frame=1; float[] data=RGBtoHSV(r,gr,b); H=data[0]; x=(int)(data[1]*128/255); y=(int)(data[2]*128/255); in=0; }
}
private void returnColor(){
// возвращаем выбранный цвет в соответствующие места
int rl;
if(frame==0)
rl=r<<16|gr<<8|b;
else rl=colordata[y*128+x];
switch(mode){
case 0: Main.main.e.color=rl;break;
case 1: Statics.edBack=rl;Main.main.e.clearBuffers();break;
case 2: Statics.curColor=rl;break;
case 3: Statics.gridColor=rl;break;
case 4: Statics.menuBack=rl;break;
case 5: Statics.textColor=rl;break;
case 6: Statics.menuTextColor=rl;Main.main.menu.menu.textColor=rl;break;
case 7: Statics.background=rl;break;
}
if(mode==0||mode==7)Main.main.toEditor(); else Main.main.toMenu();
}
/**
* Called when a key is released.
*/
protected void keyReleased(int keyCode) {
k=0;
}
/**
* Called when a key is repeated (held down).
*/
protected void keyRepeated(int keyCode) {
k=keyCode;
}
/**
* Called when the pointer is dragged.
*/
protected void pointerDragged(int xp, int yp) {
if(frame==0){
if(xp>=5&&yp>=sh+5&&xp<=ww/2+5&&yp<=25+sh){
r=(xp-5)*255/(ww/2);
}
if(xp>=15&&yp>=sh+30&&xp<=ww/2+15&&yp<=sh+50){
gr=(xp-15)*255/(ww/2);
}
if(xp>=25&&yp>=sh+55&&xp<=ww/2+25&&yp<=sh+75){
b=(xp-25)*255/(ww/2);
}
if(xp>=5&&yp>=sh+90&&xp<=ww-5&&yp<=sh+115){
frame=1;
float[] data=RGBtoHSV(r,gr,b);
H=data[0];
x=(int)(data[1]*128/255);
y=(int)(data[2]*128/255);
}
}
else if(frame==1){
if(xp>=3&&xp<=ww-3&&yp>=sh+6&&yp<=sh+24){
H=(xp-3)*360/(ww-3);
if(H>=360)H=0;
if(H<0)H=360;
upData();
}
else if(xp>=16&&yp>=sh+39&&xp<=144&&yp<=sh+167){
x=(xp-16);
y=yp-sh-39;
}
}
}
/**
* Called when the pointer is pressed.
*/
protected void pointerPressed(int xp, int yp) {
if(yp>=hh-40){
if(xp<=ww/4){
if(frame==0){
frame=1;
float[] data=RGBtoHSV(r,gr,b);
H=data[0];
x=(int)(data[1]*128/255);
y=(int)(data[2]*128/255);}
else{
frame=0;
setColor(colordata[y*128+x]);
}
}
else if(xp>=ww-ww/4){
returnColor();
}
}
if(frame==0){
if(xp>=5&&yp>=sh+5&&xp<=ww/2+5&&yp<=25+sh){
r=(xp-5)*255/(ww/2);
}
if(xp>=15&&yp>=sh+30&&xp<=ww/2+15&&yp<=sh+50){
gr=(xp-15)*255/(ww/2);
}
if(xp>=25&&yp>=sh+55&&xp<=ww/2+25&&yp<=sh+75){
b=(xp-25)*255/(ww/2);
}
if(xp>=5&&yp>=sh+90&&xp<=ww-5&&yp<=sh+115){
frame=1;
float[] data=RGBtoHSV(r,gr,b);
H=data[0];
x=(int)(data[1]*128/255);
y=(int)(data[2]*128/255);
}
}
else if(frame==1){
if(xp>=3&&xp<=ww-3&&yp>=sh+6&&yp<=sh+24){
H=(xp-3)*360/(ww-3);
if(H>=360)H=0;
if(H<0)H=360;
upData();
}
else if(xp>=16&&yp>=sh+39&&xp<=144&&yp<=sh+167){
x=(xp-16);
y=yp-sh-39;
}
}
}
/**
* Called when the pointer is released.
*/
protected void pointerReleased(int x, int y) {
}
}

507
src/Create.java Normal file
View File

@ -0,0 +1,507 @@
/*
* Класс для создания основных трехмерных фигур. Плоскость, куб, рамка-куба, тор, сфера, пирамида, диск, цилиндр и конус =)
*/
public class Create
{
public static Face[] plane(Vertex m, Vertex n, int color)
{
Vertex a=new Vertex(m), b=new Vertex(n);
if(m.x>n.x){
a.x=n.x;
b.x=m.x;
}else{
a.x=m.x;
b.x=n.x;
}
if(m.z>=n.z){
a.z=m.z;
b.z=n.z;
}else{
a.z=n.z;
b.z=m.z;
}
Triangle[] v = new Triangle[2];
Vertex v1 = new Vertex(a);
v1.setUV(0,0);
Vertex v2 = new Vertex(a.x, a.y, b.z);
v2.setUV(0, 1);
Vertex v3 = new Vertex(b.x, a.y, a.z);
v3.setUV(1, 0);
Vertex v4 = new Vertex(b.x, a.y, b.z);
v4.setUV(1, 1);
v[0] = new Triangle(v1, v2, v3, color);
v[0].norm(0,1,0);
v[0].setUV();
// v[0].setUV(new float[]{0,0,0,1,1,0});
v[1] = new Triangle(v3, v2, v4, color);
v[1].norm(0,1,0);
v[1].setUV();
// v[1].setUV(new float[]{1,0,0,1,1,1});
return v; }
public static Face[] box(Vertex m, Vertex n, int color) {
Vertex a=new Vertex(),b=new Vertex();
if(m.x>n.x){a.x=n.x;b.x=m.x;}
else{a.x=m.x;b.x=n.x;}
if(m.y>n.y){a.y=n.y;b.y=m.y;}
else{a.y=m.y;b.y=n.y;}
if(m.z>n.z){a.z=n.z;b.z=m.z;}
else{a.z=m.z;b.z=n.z;}
Triangle[] t = new Triangle[12];
Vertex[] v = new Vertex[8];
v[0] = new Vertex(a);
v[1] = new Vertex(a.x, b.y, a.z);
v[2] = new Vertex(b.x, b.y, a.z);
v[3] = new Vertex(b.x, a.y, a.z);
v[4] = new Vertex(a.x, a.y, b.z);
v[5] = new Vertex(a.x, b.y, b.z);
v[6] = new Vertex(b);
v[7] = new Vertex(b.x, a.y, b.z);
t[0] = new Triangle(v[0], v[1], v[2], color);
t[0].norm(0, 0, -1);
t[0].smooth=false;
t[0].setUV(new float[]{0,1,0,0,1,0});
t[1] = new Triangle(v[2], v[3], v[0], color);
t[1].norm(0, 0, -1);
t[1].smooth=false;
t[1].setUV(new float[]{1,0,1,1,0,1});
t[2] = new Triangle(v[0], v[1], v[5], color);
t[2].norm(-1, 0, 0);
t[2].smooth=false;
t[2].setUV(new float[]{1,1,1,0,0,0});
t[3] = new Triangle(v[5], v[4], v[0], color);
t[3].norm(-1, 0, 0);
t[3].smooth=false;
t[3].setUV(new float[]{0,0,0,1,1,1});
t[4] = new Triangle(v[3], v[2], v[6], color);
t[4].norm(1,0,0);
t[4].smooth=false;
t[4].setUV(new float[]{0,1,0,0,1,0});
t[5] = new Triangle(v[6], v[7], v[3], color);
t[5].norm(1,0,0);
t[5].smooth=false;
t[5].setUV(new float[]{1,0,1,1,0,1});
t[6] = new Triangle(v[1], v[5], v[6], color);
t[6].norm(0,1,0);
t[6].smooth=false;
t[6].setUV(new float[]{0,1,0,0,1,0});
t[7] = new Triangle(v[6], v[2], v[1], color);
t[7].norm(0,1,0);
t[7].smooth=false;
t[7].setUV(new float[]{1,0,1,1,0,1});
t[8] = new Triangle(v[0], v[4], v[7], color);
t[8].norm(0,-1,0);
t[8].smooth=false;
t[8].setUV(new float[]{0,0,0,1,1,1});
t[9] = new Triangle(v[7], v[3], v[0], color);
t[9].norm(0,-1,0);
t[9].smooth=false;
t[9].setUV(new float[]{1,1,1,0,0,0});
t[10] = new Triangle(v[4], v[5], v[6], color);
t[10].norm(0,0,1);
t[10].smooth=false;
t[10].setUV(new float[]{1,1,1,0,0,0});
t[11] = new Triangle(v[6], v[7], v[4], color);
t[11].norm(0,0,1);
t[11].smooth=false;
t[11].setUV(new float[]{0,0,0,1,1,1});
return t; }
public static Face[] wireBox(Vertex a,Vertex b,int color){
Line[] l=new Line[12];
Vertex[] v=new Vertex[8];
v[0] = new Vertex(a);
v[1] = new Vertex(a.x, b.y, a.z);
v[2] = new Vertex(b.x, b.y, a.z);
v[3] = new Vertex(b.x, a.y, a.z);
v[4] = new Vertex(a.x, a.y, b.z);
v[5] = new Vertex(a.x, b.y, b.z);
v[6] = new Vertex(b);
v[7] = new Vertex(b.x, a.y, b.z);
l[0]=new Line(v[0],v[3],color);
l[1]=new Line(v[0],v[1],color);
l[2]=new Line(v[1],v[2],color);
l[3]=new Line(v[2],v[3],color);
l[4]=new Line(v[0],v[4],color);
l[5]=new Line(v[1],v[5],color);
l[6]=new Line(v[2],v[6],color);
l[7]=new Line(v[3],v[7],color);
l[8]=new Line(v[4],v[5],color);
l[9]=new Line(v[5],v[6],color);
l[10]=new Line(v[6],v[7],color);
l[11]=new Line(v[4],v[7],color);
return l;
}
public static Face[] torus(Vertex c, int R1, int R2, int SEGS1, int SEGS2, int color) {
int j;
int n = 0;
if ((SEGS1 < 2) || (SEGS2 < 2)) return null;
int numVerts = 0;
int numFaces = 0;
Vertex[] verts = new Vertex[SEGS1 * SEGS2];
Triangle[] faces = new Triangle[SEGS1 * SEGS2 * 2];
for (int i = 0; i < SEGS1; ++i)
for (j = 0; j < SEGS2; ++j) {
verts[numVerts] = new Vertex();
float a1 = i * 6.2831854820251465F / SEGS1;
float a2 = j * 6.2831854820251465F / SEGS2;
int cx = (int)((R1 + R2 * Math.cos(a2)) * Math.cos(a1));
int cz = (int)((R1 + R2 * Math.cos(a2)) * Math.sin(a1));
int cy = (int)(R2 * Math.sin(a2));
verts[numVerts].u = 1024 * i / SEGS1;
verts[numVerts].u/=1024;
verts[numVerts].v = 256 * j / SEGS2;
verts[numVerts].v/=256;
verts[numVerts].x = (cx + c.x);
verts[numVerts].y = (cy + c.y);
verts[numVerts].z = (cz + c.z);
++numVerts;
}
for (int i = 0; i < SEGS1; ++i) {
for (j = 0; j < SEGS2; ++j) {
faces[numFaces] = new Triangle(nv(), nv(), nv(), color);
faces[numFaces].a = verts[(n + j)];
faces[numFaces].b = verts[((n + (j + 1) % SEGS2) % numVerts)];
faces[numFaces].c = verts[((n + (j + 1) % SEGS2 + SEGS2) % numVerts)];
faces[numFaces].norm();
faces[numFaces].setUV(new float[]{faces[numFaces].a.u,faces[numFaces].a.v,faces[numFaces].b.u,faces[numFaces].b.v,faces[numFaces].c.u,faces[numFaces].c.v});
numFaces++;
faces[numFaces] = new Triangle(nv(), nv(), nv(), color);
faces[numFaces].a = verts[((n + (j + 1) % SEGS2 + SEGS2) % numVerts)];
faces[numFaces].b = verts[((n + j + SEGS2) % numVerts)];
faces[numFaces].c = verts[(n + j)];
faces[numFaces].norm();
faces[numFaces].setUV(new float[]{faces[numFaces].a.u,faces[numFaces].a.v,faces[numFaces].b.u,faces[numFaces].b.v,faces[numFaces].c.u,faces[numFaces].c.v});
numFaces++;
}
n += SEGS2;
}
return faces; }
static Vertex nv() {
return new Vertex(); }
public static Face[] pyramid(Vertex c, Vertex c2, int h, int color) {
Triangle[] t = new Triangle[6];
Vertex[] v = new Vertex[5];
if(c2.x<c.x) c2.x=c.x+(c.x-c2.x);
if(c2.z>c.z) c2.z=c.z-(c2.z-c.z);
v[0] = new Vertex(c.x, c.y + h, c.z);
v[1] = new Vertex(c2);
int cx = c.x - c2.x + c.x; int cz = c.z + c.z - c2.z;
v[2] = new Vertex(cx, c.y, c2.z);
v[3] = new Vertex(cx, c.y, cz);
v[4] = new Vertex(c2.x, c.y, cz);
t[0] = new Triangle(v[1], v[2], v[3], color);
t[0].norm();
t[0].smooth=false;
t[0].setUV(new float[]{1,0,0,0,0,1});
t[1] = new Triangle(v[3], v[4], v[1], color);
t[1].norm();
t[1].smooth=false;
t[1].setUV(new float[]{0,1,1,1,1,0});
if(h>0){t[0].invert();t[1].invert();}
t[2] = new Triangle(v[2], v[0], v[1], color);
t[2].norm();
t[2].smooth=false;
t[2].setUV(new float[]{0,1,0.5F,0,1,1});
t[3] = new Triangle(v[2], v[0], v[3], color);
t[3].norm();
t[3].smooth=false;
t[3].setUV(new float[]{1,1,0.5F,0,0,1});
t[4] = new Triangle(v[1], v[0], v[4], color);
t[4].norm();
t[4].smooth=false;
t[4].setUV(new float[]{0,1,0.5F,0,1,1});
t[5] = new Triangle(v[3], v[0], v[4], color);
t[5].norm();
t[5].smooth=false;
t[5].setUV(new float[]{1,1,0.5F,0,0,1});
if(h>0){t[3].invert();t[5].invert();}else{t[2].invert();t[4].invert();}
return t;
}
public static Face[] disk(Vertex c,double r,int slices,int color){
double angle = 6.2831853071795862D / (double)slices;
Triangle[] t=new Triangle[slices];
Vertex[] vx=new Vertex[slices+1];
vx[0]=new Vertex(c);
vx[0].setUV(0.5F, 0.5F);
for(int i=1;i<vx.length;i++){
vx[i]=new Vertex(0,0,0);
vx[i].x = (int)(r * Math.cos(angle * (double)i)+c.x);
vx[i].z = (int)(r * Math.sin(angle * (double)i)+c.z);
vx[i].y = c.y;
vx[i].u=(float)(0.5 * Math.cos(angle * (double)i)+0.5);
vx[i].v=(float)(0.5 * Math.sin(angle * (double)i)+0.5);
}
for (int i=0;i<t.length;i++){
if(i==slices-1)t[i]=new Triangle(vx[0],vx[slices],vx[1],color);
else t[i]=new Triangle(vx[0],vx[i+1],vx[i+2],color);
t[i].norm(0,1,0);
t[i].smooth=false;
t[i].setUV();
}
return t;
}
public static Face[] cylinder(Vertex c,double r,int h,int slices,int color){
double angle = 6.2831853071795862D / (double)slices;
Triangle[] t=new Triangle[slices*4];
Vertex[] vx=new Vertex[slices+1],v=new Vertex[slices+1];
vx[0]=new Vertex(c);
vx[0].u=vx[0].v=0.5f;
v[0]=new Vertex(c.x,c.y+h,c.z);
v[0].u=v[0].v=0.5f;
for(int i=1;i<vx.length;i++){
vx[i]=new Vertex(0,0,0);
v[i]=new Vertex(0,0,0);
vx[i].x= v[i].x = (int)(r * Math.cos(angle * (double)i)+c.x);
vx[i].z=v[i].z = (int)(r * Math.sin(angle * (double)i)+c.z);
vx[i].y = c.y;
v[i].y=c.y+h;
vx[i].u=(float)(0.5 * Math.cos(angle * (double)i)+0.5);
vx[i].v=(float)(0.5 * Math.sin(angle * (double)i)+0.5);
v[i].u=(float)(0.5 * Math.cos(angle * (double)i)+0.5);
v[i].v=(float)(0.5 * Math.sin(angle * (double)i)+0.5);
}
int j;
for (int i=0;i<=(slices-1)*4;i+=4){
j=i/4;
if(i==(slices-1)*4){
t[i]=new Triangle(vx[0],vx[slices],vx[1],color);
t[i].norm();
t[i+1]=new Triangle(vx[slices],vx[1],v[slices],color);
t[i+1].norm();
t[i+2]=new Triangle(vx[1],v[slices],v[1],color);
t[i+2].norm();
t[i+3]=new Triangle(v[0],v[slices],v[1],color);
t[i+3].norm();
}
else{
t[i]=new Triangle(vx[0],vx[j+1],vx[j+2],color);
t[i].norm();
t[i+1]=new Triangle(vx[j+1],vx[j+2],v[j+1],color);
t[i+1].norm();
t[i+2]=new Triangle(vx[j+2],v[j+1],v[j+2],color);
t[i+2].norm();
t[i+3]=new Triangle(v[0],v[j+1],v[j+2],color);
t[i+3].norm();
}
t[i].smooth=false;
t[i+3].smooth=false;
t[i].setUV();
t[i+1].setUV();
t[i+2].setUV();
t[i+3].setUV();
if(h>0){t[i+3].invert();t[i+1].invert();}else{t[i].invert();t[i+2].invert();}
}
return t;
}
public static Face[] cone(Vertex c,double r,int h,int slices,int color){
double angle = 6.2831853071795862D / (double)slices;
Triangle[] t=new Triangle[slices*2];
Vertex[] v=new Vertex[slices+2];
v[0]=new Vertex(c);
v[v.length-1]=new Vertex(c.x,c.y+h,c.z);
v[0].u=v[0].v=0.5f;
v[v.length-1].u=v[v.length-1].v=0.5f;
for(int i=1;i<v.length-1;i++){
v[i]=new Vertex(0,0,0);
v[i].x = (int)(r * Math.cos(angle * (double)i)+c.x);
v[i].z = (int)(r * Math.sin(angle * (double)i)+c.z);
v[i].y = c.y;
v[i].u = (float)(0.5 * Math.cos(angle * (double)i)+0.5);
v[i].v = (float)(0.5 * Math.sin(angle * (double)i)+0.5);
}
int j;
for (int i=0;i<slices;i++){
j=i*2;
if(i==slices-1){
t[j]=new Triangle(v[0],v[slices],v[1],color);
t[j].norm();
t[j+1]=new Triangle(v[1],v[slices],v[v.length-1],color);
t[j+1].norm();
}
else{
t[j]=new Triangle(v[0],v[i+1],v[i+2],color);
t[j].norm();
t[j+1]=new Triangle(v[i+1],v[i+2],v[v.length-1],color);
t[j+1].norm();
}
t[j].smooth=false;
t[j].setUV();
t[j+1].setUV();
if(h>0&&i!=slices-1){t[j+1].invert();}else if(h<0){t[j].invert();if(i==slices-1)t[j+1].invert();}
}
return t;
}
public static Face[] sphere(Vertex c,double gRad,int gnRings,int gnSects,int color){
// общее количество треугольников будет:
int gnTria = (gnRings+1) * gnSects * 2;
//===Нетрудно подсчитать и общее количество вершин:
int gnVert = (gnRings+1) * gnSects + 2;
//====== Формирование массива вершин
Triangle[] t=new Triangle[gnTria];
Vertex[] v=new Vertex[gnVert];
//====== Северный полюс
v[0] = new Vertex (c.x, c.y+(int)gRad, c.z);
//====== Индекс последней вершины (на южном полюсе)
int last = gnVert - 1; //====== Южный полюс
v[last] = new Vertex (c.x, c.y-(int)gRad, c.z);
v[0].u=v[0].v=0;
v[last].u=0;
v[last].v=1;
//====== Подготовка констант
double da = Math.PI / (gnRings +2),
db = 2 * Math.PI / gnSects,
af = Math.PI - da/2;
double bf = 2 * Math.PI - db/2;
//=== Индекс вершины, следующей за северным полюсом
int n = 1;
//=== Цикл по широтам
for ( double a = da; a < af; a += da)
{
//=== Координата у постоянна для всего кольца
double у = gRad * Math.cos(a),
//====== Вспомогательная точка
xz = gRad * Math.sin(a);
//====== Цикл по секциям (долгота)
for ( double b = 0.; b < bf; n++, b += db)
{
// Координаты проекции в экваториальной плоскости
double x = xz * Math.sin(b);
double z = xz * Math.cos(b);
v[n] = new Vertex ((int)x+c.x, (int)у+c.y, (int)z+c.z);
v[n].u=(float)(b/bf);
v[n].v=(float)(a/af);
} }
//====== Формирование массива индексов
//====== Треугольники вблизи полюсов
for (n = 0; n < gnSects; n++)
{
t[n]=new Triangle(v[0],v[n + 1],n == gnSects - 1 ? v[1] : v[n + 2],color);
t[n].norm();
if(n==gnSects-1)
t[n].setUV(new float[]{v[0].u,v[0].v,v[n+1].u,v[n+1].v,1,v[n+1].v});
else t[n].setUV(new float[]{(v[n+1].u+v[n+2].u)/2,v[0].v,v[n+1].u,v[n+1].v,v[n+2].u,v[n+2].v});
//====== Индекс общей вершины (северный полюс)
//====== Индекс общей вершины (южный полюс)
t[gnTria-gnSects+n]=new Triangle(v[last],v[last-1-n],v[last-1 - ( (1 + n) % gnSects)],color);
t[gnTria-gnSects+n].norm();
if(n==gnSects-1)
t[gnTria-gnSects+n].setUV(new float[]{v[last].u,v[last].v,v[last-1-n].u,v[last-1-n].v,1,v[last-1-n].v});
else t[gnTria-gnSects+n].setUV(new float[]{(v[last-1-n].u+v[last-1 - ( (1 + n) % gnSects)].u)/2,v[last].v,v[last-1-n].u,v[last-1 - n].v,v[last-1 - ( (1 + n) % gnSects)].u,v[last-1 - ( (1 + n) % gnSects)].v});
}
//====== Треугольники разбиения колец
//====== Вершина, следующая за полюсом
int k = 1;
//====== gnSects - номер следующего треугольника
n = gnSects;
for (int i = 0; i < gnRings; i++, k += gnSects) {
for (int j = 0; j < gnSects; j++, n += 2) {
//======= Индекс общей вершины
t[n]=new Triangle(v[k + j],v[k + gnSects + j],v[k + gnSects + ((j + 1) % gnSects)],color);
t[n].norm();
if(j==gnSects-1)
t[n].setUV(new float[]{v[k+j].u,v[k+j].v,v[k+gnSects+j].u,v[k+gnSects+j].v,1,v[k + gnSects + ((j + 1) % gnSects)].v});
else t[n].setUV(new float[]{v[k+j].u,v[k+j].v,v[k+gnSects+j].u,v[k+gnSects+j].v,v[k + gnSects + ((j + 1) % gnSects)].u,v[k + gnSects + ((j + 1) % gnSects)].v});
//======= Индекс текущей вершины
//======= Замыкание
//======= To же для второго треугольника
t[n+1]=new Triangle(t[n].a,t[n].c,v[k + ((j + 1) % gnSects)],color);
t[n+1].norm();
if(j==gnSects-1)
t[n+1].setUV(new float[]{t[n].uv[0],t[n].uv[1],t[n].uv[4],t[n].uv[5],1,v[k + ((j + 1) % gnSects)].v});
else t[n+1].setUV(new float[]{t[n].uv[0],t[n].uv[1],t[n].uv[4],t[n].uv[5],v[k + ((j + 1) % gnSects)].u,v[k + ((j + 1) % gnSects)].v});
}}
return t;
}
}
/* public static void calcNormals(Triangle[] faces)
{
for (int i = 0; i < faces.length; i++) {
float ax = faces[i].c.x - faces[i].a.x;
float ay = faces[i].c.y - faces[i].a.y;
float az = faces[i].c.z - faces[i].a.z;
float bx = faces[i].b.x - faces[i].a.x;
float by = faces[i].b.y - faces[i].a.y;
float bz = faces[i].b.z - faces[i].a.z;
float nx = ay * bz - az * by;
float ny = az * bx - ax * bz;
float nz = ax * by - ay * bx;
double l = Math.sqrt(nx * nx + ny * ny + nz * nz);
faces[i].nx /=l;
faces[i].ny /=l;
faces[i].nz /=l;
}
}*/

566
src/Edit.java Normal file
View File

@ -0,0 +1,566 @@
/*
* Это окно редактирования, ну то, что открывается по нажатию на клавишу 9.
*/
/*
* To change this template, choose Tools | Templates and open the template in
* the editor.
*/
import javax.microedition.lcdui.*;
/**
* @author Shaman
*/
public class Edit extends Canvas{
int w,h,md,xs,ys,cx,cy,tn; // md - текущее меню
public static int mo; // текущий режим. 0 - объекты, 1 - полигоны, 2 - вершины.
Menu m;
Image modes,tex;
Triangle sel;
int selv=0;
boolean mv=false;
Font f;
int sh;
/**
* constructor
*/
public Edit() {
setFullScreenMode(true);
m = new Menu(null, Statics.font);
w=getWidth();
h=getHeight();
f=Statics.font;
sh=f.getHeight();
try{
modes=Image.createImage("/img/"+(Statics.bigImages?"60":"30")+"/modes.png");
}catch(Exception e){}
toEdit();
}
/**
* paint
*/
public void paint(Graphics g) {
g.setColor(Statics.menuBack);
g.fillRect(0, 0, w, h);
if(md!=1){ // если мы в обычном меню
m.paint(g, 0, h/3, w, h, 1);
g.setColor(0x888888);
g.fillRoundRect(w/2-modes.getWidth()/2+mo*(Statics.bigImages?66:33), h/3-(Statics.bigImages?60:30)-modes.getHeight()/2, (Statics.bigImages?60:30), (Statics.bigImages?60:30), 15, 15);
//g.setColor(0x333333);
//g.drawRoundRect(w/2-modes.getWidth()/2+mo*33, h/3-30-modes.getHeight()/2, 31, 31, 20, 20);
g.setColor(0xbbbbbb);
g.drawRoundRect(w/2-modes.getWidth()/2+mo*(Statics.bigImages?66:33)-1, h/3-(Statics.bigImages?60:30)-modes.getHeight()/2-1, (Statics.bigImages?62:31), (Statics.bigImages?62:31), 15, 15);
g.setColor(0x888888);
g.drawRoundRect(w/2-modes.getWidth()/2+mo*(Statics.bigImages?66:33), h/3-(Statics.bigImages?60:30)-modes.getHeight()/2, (Statics.bigImages?60:30), (Statics.bigImages?60:30), 15, 15);
g.drawImage(modes, w/2, h/3-modes.getHeight(), 3);
drawLeftSoft(g,Statics.russian?"Назад":"Back");
drawRightSoft(g,Statics.russian?"Выбрать":"Select");
}
else{ // или если в режиме редактирования UV-координат для вершин
g.setColor(0);
g.drawRect(5, 5, w-10, h-50);
if(tex!=null)g.drawImage(tex, 5, 5, 20);
if(mo==1&&Editor.sel2!=null){
for(int i=0;i<Editor.sel2.size();i++){
Triangle t=(Triangle)Editor.sel2.elementAt(i);
if(t.uv==null)t.uv=new float[6];
if(sel!=null&&sel==t)g.setColor(229,106,156); else g.setColor(106,229,156);
g.drawLine((int)(t.uv[0]*(w-10)+5), (int)(t.uv[1]*(h-50)+5), (int)(t.uv[2]*(w-10)+5), (int)(t.uv[3]*(h-50)+5));
g.drawLine((int)(t.uv[0]*(w-10)+5), (int)(t.uv[1]*(h-50)+5), (int)(t.uv[4]*(w-10)+5), (int)(t.uv[5]*(h-50)+5));
g.drawLine((int)(t.uv[2]*(w-10)+5), (int)(t.uv[3]*(h-50)+5), (int)(t.uv[4]*(w-10)+5), (int)(t.uv[5]*(h-50)+5));
if(sel!=null&&selv==1)g.setColor(0xaa0000); else g.setColor(0x99);
g.fillRect((int)(t.uv[0]*(w-10)), (int)(t.uv[1]*(h-50)),10,10);
if(sel!=null&&selv==2)g.setColor(0xaa0000); else g.setColor(0x99);
g.fillRect((int)(t.uv[2]*(w-10)), (int)(t.uv[3]*(h-50)),10,10);
if(sel!=null&&selv==3)g.setColor(0xaa0000); else g.setColor(0x99);
g.fillRect((int)(t.uv[4]*(w-10)), (int)(t.uv[5]*(h-50)),10,10);
}
}
if(!Statics.touch){
g.setColor(0xff0000);
g.fillArc(cx-5, cy-5, 20, 20, 0, 360);
}
g.setColor(0);
int ld=Statics.font.stringWidth("Ok")+5;
g.drawRect(ld, h-40, w-ld-10, 40);
g.drawLine((w-ld-10)/2+ld, h-40,(w-ld-10)/2+ld, h-1);
g.drawString("<", (w-ld-10)/4+ld, h-25, Graphics.TOP|Graphics.HCENTER);
g.drawString(">", w-(w-ld-10)/4, h-25, Graphics.TOP|Graphics.HCENTER);
drawLeftSoft(g,"Ok");
}
repaint();
}
private void toEdit(){
md=0;
if(mo!=1)m.setElems(new String[]{Statics.russian?"Свойства":"Properties",Statics.russian?"UV-координаты":"UV-coord",Statics.russian?"Нормали":"Normals",Statics.russian?"Сглаживание":"Smooth",Statics.russian?"Пробный материал":"Test material",Statics.russian?"Удалить материал":"Delete material",Statics.russian?"Удалить":"Delete"});
else m.setElems(new String[]{Statics.russian?"Свойства":"Properties",Statics.russian?"UV-координаты":"UV-coord",Statics.russian?"Нормали":"Normals",Statics.russian?"Сглаживание":"Smooth",Statics.russian?"Пробный материал":"Test material",Statics.russian?"Удалить материал":"Delete material",Statics.russian?"Удалить":"Delete",Statics.russian?"Отделить":"Detach"});
}
private void toUV(){
if(mo==1){
md=1;
mv=false;
sel=null;
}
}
private void toNormals(){
md=2;
m.setElems(new String[]{Statics.russian?"Обратить":"Inverse",Statics.russian?"Пересчитать":"Recalculate"});
}
private void toSmooth(){
md=3;
m.setElems(new String[]{Statics.russian?"Вкл":"On",Statics.russian?"Выкл":"Off"});
}
/**
* Called when a key is pressed.
*/
protected void keyPressed(int key) {
int ga=getGameAction(key);
switch(ga){
case UP: if(md==1){ if(mv)move(0,-5); else if(cy>=5)cy-=5; } else m.up();break;
case DOWN: if(md==1){ if(mv)move(0,5); else if(cy<=h-55)cy+=5; } else m.down();break;
case RIGHT:if(md==1){ if(mv)move(5,0); else if(cx<=w-15)cx+=5; } else if(mo<2){mo++;
toEdit();}break;
case LEFT:if(md==1){ if(mv)move(-5,0); else if(cx>=5)cx-=5; } else if(mo>0){mo--;
toEdit();}break;
case FIRE: if(md==1){
if(!mv){
select(cx,cy);
}
else mv=false;
} else fire();break;
}
String strCode = null;
try {
strCode = getKeyName(key).toLowerCase();
}
catch (IllegalArgumentException e) {
}
if (strCode != null)
{
if (((("soft1".equals(strCode)) || ("soft 1".equals(strCode)) || ("soft_1".equals(strCode)) || ("softkey 1".equals(strCode)) || ("sk2(left)".equals(strCode)) || (strCode.startsWith("left soft")))))
{ back(); return;}//left
if (("soft2".equals(strCode)) || ("soft 2".equals(strCode)) || ("soft_2".equals(strCode)) || ("softkey 4".equals(strCode)) || ("sk1(right)".equals(strCode)) || (strCode.startsWith("right soft")))
{fire();return; }//right
}
switch (key)
{
case -202:
case -21:
case -6:
case 21:
case 105:
case 113:
case 57345:
back();break;//left
case -203:
case -22:
case -7:
case 22:
case 106:
case 112:
case 57346:
fire();break;//right
}
if(md==1){
if(key==KEY_STAR){
tn--;
if(tn<0){if(MaterialEditor.mat!=null&&!MaterialEditor.mat.isEmpty())tn=MaterialEditor.mat.size(); else tn=0; }
updImg();
}
if(key==KEY_POUND){
if(MaterialEditor.mat!=null&&!MaterialEditor.mat.isEmpty()){
tn++;
if(tn>MaterialEditor.mat.size())tn=0;
}
updImg();
}
}
}
private void updImg(){
// обновление заднего изображения из доступных текстур в редакторе материалов
if(tn==0||MaterialEditor.mat==null||tn>MaterialEditor.mat.size()){
tex=null;
return;}
Material mat=(Material)MaterialEditor.mat.elementAt(tn-1);
if(mat.texture==null){tex=null;return; }
tex=Main.resizeImage(Image.createRGBImage(mat.texture, mat.w, mat.h, false), w-10, h-50);
}
private void drawLeftSoft(Graphics g,String s){
if(!Statics.touch){
g.setColor(8947967);
g.fillRoundRect(0, h - sh+1, g.getFont().stringWidth(s)+5, sh-1,10,10);
g.setColor(0);
g.drawRoundRect(0, h - sh+1, g.getFont().stringWidth(s)+5, sh-2,10,10);
g.setColor(0x555555);
g.drawString(s, 2, h - 2, 36);
g.setColor(Statics.textColor);
g.drawString(s, 3, h - 1, 36);}
else{
g.setColor(8947967);
g.fillRoundRect(0, h - 40, g.getFont().stringWidth(s)+5, 39,15,15);
g.setColor(0);
g.drawRoundRect(0, h - 40, g.getFont().stringWidth(s)+5, 38,15,15);
g.setColor(0x555555);
g.drawString(s, 2, h + sh/2 - 20, 36);
g.setColor(Statics.textColor);
g.drawString(s, 3, h +sh/2 - 19, 36);
}
}
private void drawRightSoft(Graphics g,String s){
if(!Statics.touch){
g.setColor(8947967);
g.fillRoundRect(w-g.getFont().stringWidth(s)-5, h - sh + 1, g.getFont().stringWidth(s)+5, sh-1,10,10);
g.setColor(0);
g.drawRoundRect(w-g.getFont().stringWidth(s)-5, h - sh + 1, g.getFont().stringWidth(s)+4, sh-2,10,10);
g.setColor(0x555555);
g.drawString(s, w - 4, h - 2, 40);
g.setColor(Statics.textColor);
g.drawString(s, w - 3, h - 1, 40);}
else{
g.setColor(8947967);
g.fillRoundRect(w-g.getFont().stringWidth(s)-5, h - 40, g.getFont().stringWidth(s)+5, 39,15,15);
g.setColor(0);
g.drawRoundRect(w-g.getFont().stringWidth(s)-5, h-40, g.getFont().stringWidth(s)+4, 38,15,15);
g.setColor(0x555555);
g.drawString(s, w - 4, h+sh/2- 20, 40);
g.setColor(Statics.textColor);
g.drawString(s, w - 3, h+sh/2 - 19, 40);
}
}
private void select(int xs,int ys){ // выбор вершин при редактировании uv
if(Editor.sel2==null||Editor.sel2.isEmpty())return;
boolean flg=false;
for(int i=0;i<Editor.sel2.size();i++){
Triangle t=(Triangle)Editor.sel2.elementAt(i);
if(xs>=t.uv[0]*(w-5)-5&&xs<=t.uv[0]*(w-5)+5&&ys>=t.uv[1]*(h-55)-5&&ys<=t.uv[1]*(h-55)+5){
sel=t;
selv=1;
flg=true;
break;
}
if(xs>=t.uv[2]*(w-5)-5&&xs<=t.uv[2]*(w-5)+5&&ys>=t.uv[3]*(h-55)-5&&ys<=t.uv[3]*(h-55)+5){
sel=t;
selv=2;
flg=true;
break;
}
if(xs>=t.uv[4]*(w-5)-5&&xs<=t.uv[4]*(w-5)+5&&ys>=t.uv[5]*(h-55)-5&&ys<=t.uv[5]*(h-55)+5){
sel=t;
selv=3;
flg=true;
break;
}
if(!flg){
int ai=(int)((t.uv[0]*(w-5) - xs) * (t.uv[3]*(h-55) - t.uv[1]*(h-55)) - (t.uv[2]*(w-5) - t.uv[0]*(w-5)) * (t.uv[1]*(h-55) - ys));
int bi=(int)((t.uv[2]*(w-5) - xs) * (t.uv[5]*(h-55) - t.uv[3]*(h-55)) - (t.uv[4]*(w-5) - t.uv[2]*(w-5)) * (t.uv[3]*(h-55) - ys));
int ci=(int)((t.uv[4]*(w-5) - xs) * (t.uv[1]*(h-55) - t.uv[5]*(h-55)) - (t.uv[0]*(w-5) - t.uv[4]*(w-5)) * (t.uv[5]*(h-55) - ys));
if((ai>=0&&bi>=0&&ci>=0)||(ai<=0&&bi<=0&&ci<=0)){ sel=t;
selv=0;
flg=true;
break;
}
}
}
mv=flg;
}
private void move(int xs,int ys){ // двигаем UV-координаты выбранного полигона
if(sel!=null){
if(selv==0||selv==1){
sel.uv[0]+=(float)(xs)/(w-5);
sel.uv[1]+=(float)(ys)/(h-55);
}
if(selv==0||selv==2){
sel.uv[2]+=(float)(xs)/(w-5);
sel.uv[3]+=(float)(ys)/(h-55);
}
if(selv==0||selv==3){
sel.uv[4]+=(float)(xs)/(w-5);
sel.uv[5]+=(float)(ys)/(h-55);
}
}
}
public void fire(){ // метод при нажатии на 5 или Ок
switch(m.index){
case 4: Material ma=new Material();
Image tex=null;
try{
tex=Image.createImage("/img/30/tex.jpg");
}catch(Exception e){}
ma.setDiffuseMap(tex);
ma.self=0.2f;
//m.opacity=200;
Main.main.e.m.setMaterial(ma); MaterialEditor.mat.addElement(ma); Main.main.toEditor(); break;
case 0: if(md==2){ inverse(); Main.main.toEditor();} else if(md==3){smoothOn(); Main.main.toEditor();}
else
if(Editor.sel!=null&&Editor.sel.size()==1&&Editor.sel.firstElement() instanceof Group){
Form fo=new Form(Statics.russian?"Свойства":"Properties");
Main.main.d.setCurrent(fo);
fo.addCommand(new Command("Ok",1,1));
final TextField nm=new TextField(Statics.russian?"Имя:":"Name",((Group)(Editor.sel.elementAt(0))).name,50,TextField.ANY);
fo.append(nm);
final ChoiceGroup cg=new ChoiceGroup("",List.MULTIPLE,new String[]{Statics.russian?"Видимый":"Visible"},null);
cg.setSelectedFlags(new boolean[]{((Group)(Editor.sel.elementAt(0))).visible});
fo.append(cg);
fo.append(""+((Group)(Editor.sel.elementAt(0))).f.size()+(Statics.russian?" полигонов":" triangles"));
fo.append(""+((Group)(Editor.sel.elementAt(0))).v.size()+(Statics.russian?" вершин":" vertexes"));
fo.setCommandListener(new CommandListener(){
public void commandAction(Command c,Displayable dis){
((Group)(Editor.sel.elementAt(0))).name=nm.getString();
((Group)(Editor.sel.elementAt(0))).visible=cg.isSelected(0);
Main.main.toEdit();
}
});
} break;
case 1: if(md==0)toUV(); else if(md==2){recalculateNormals(); Main.main.toEditor();} else if(md==3){smoothOff(); Main.main.toEditor();} break;
case 2: toNormals(); break;
case 3: toSmooth(); break;
case 5: deleteMaterial(); Main.main.toEditor(); break;
case 6: if(mo==0&&Editor.sel!=null){
for(int i=0;i<Editor.sel.size();i++){
if(Editor.sel.elementAt(i) instanceof Light)
Main.main.e.m.deleteLight((Light)Editor.sel.elementAt(i));
else Main.main.e.m.g.removeElement(Editor.sel.elementAt(i));
}
}
else if(mo==1&&Editor.sel2!=null){
for(int i=0;i<Editor.sel2.size();i++)
Main.main.e.m.deleteFace((Face)Editor.sel2.elementAt(i));
}
else if(mo==2&&Editor.sel3!=null){
for(int i=0;i<Editor.sel3.size();i++)
Main.main.e.m.deleteVertex((Vertex)Editor.sel3.elementAt(i));
}
Editor.sel=null;
Editor.sel2=null;
Editor.sel3=null;
System.gc();
Main.main.toEditor();
break;
case 7: if(Editor.sel2==null)break;
Group gr=new Group();
gr.name="Object_"+Main.main.e.m.g.size();
for(int i=0;i<Editor.sel2.size();i++){
Triangle tr=(Triangle)Editor.sel2.elementAt(i);
Main.main.e.m.deleteFace(tr);
tr.a=new Vertex(tr.a);
tr.b=new Vertex(tr.b);
tr.c=new Vertex(tr.c);
gr.add(tr);
}
gr.countBoundary();
Main.main.e.m.add(gr);
//Editor.sel2=null;
Main.main.toEditor();
break;
}
}
private void back(){ // назад
if(md==0) Main.main.toEditor();
else toEdit();
}
private void deleteMaterial(){ // удаляем материал с выбранных объектов или полигонов
if(mo==0&&Editor.sel!=null){
for(int i=0;i<Editor.sel.size();i++){
if(!(Editor.sel.elementAt(i) instanceof Group))continue;
Group gr=(Group)Editor.sel.elementAt(i);
for(int j=0;j<gr.f.size();j++)
((Triangle)gr.f.elementAt(j)).material=null;
}
}
else if(mo==1&&Editor.sel2!=null){
for(int i=0;i<Editor.sel2.size();i++)
((Triangle)Editor.sel2.elementAt(i)).material=null;
}
}
private void inverse(){ // обращение нормалей, у полигонов свои нормали, у вершин свои, но рассчитываемые из полигонных (это для сглаживания освещения).
if(mo==0&&Editor.sel!=null){
for(int i=0;i<Editor.sel.size();i++){
if(!(Editor.sel.elementAt(i) instanceof Group))continue;
Group gr=(Group)Editor.sel.elementAt(i);
for(int j=0;j<gr.f.size();j++)
((Triangle)gr.f.elementAt(j)).invert();
}
}
else if(mo==1&&Editor.sel2!=null){
for(int i=0;i<Editor.sel2.size();i++){
((Triangle)Editor.sel2.elementAt(i)).invert();
}
}
else if(mo==3&&Editor.sel3!=null){
for(int i=0;i<Editor.sel3.size();i++){
Vertex ver=((Vertex)Editor.sel2.elementAt(i));
ver.nx=-ver.nx;
ver.ny=-ver.ny;
ver.nz=-ver.nz;
}
}
}
private void recalculateNormals(){ // пересчет нормалей
if(mo==0&&Editor.sel!=null){
for(int i=0;i<Editor.sel.size();i++){
if(!(Editor.sel.elementAt(i) instanceof Group))continue;
Group gr=(Group)Editor.sel.elementAt(i);
gr.triNorm();
gr.verNorm();
}
}
else if(mo==1&&Editor.sel2!=null){
for(int i=0;i<Editor.sel2.size();i++){
((Triangle)Editor.sel2.elementAt(i)).norm();
}
}
else if(mo==2&&Editor.sel3!=null){
for(int i=0;i<Editor.sel3.size();i++){
Vertex ver=(Vertex)Editor.sel3.elementAt(i);
Main.main.e.m.vertexNorm(ver);
}
}
}
private void smoothOn(){ // включение сглажвания между полигонами при освещении
if(mo==0&&Editor.sel!=null){
for(int i=0;i<Editor.sel.size();i++){
if(!(Editor.sel.elementAt(i) instanceof Group))continue;
Group gr=(Group)Editor.sel.elementAt(i);
for(int j=0;j<gr.f.size();j++){
((Triangle)gr.f.elementAt(j)).smooth=true;
}
}
}
else if(mo==1&&Editor.sel2!=null){
for(int i=0;i<Editor.sel2.size();i++){
((Triangle)Editor.sel2.elementAt(i)).smooth=true;
}
}
}
private void smoothOff(){ // выключение
if(mo==0&&Editor.sel!=null){
for(int i=0;i<Editor.sel.size();i++){
if(!(Editor.sel.elementAt(i) instanceof Group))continue;
Group gr=(Group)Editor.sel.elementAt(i);
for(int j=0;j<gr.f.size();j++){
((Triangle)gr.f.elementAt(j)).smooth=false;
}
}
}
else if(mo==1&&Editor.sel2!=null){
for(int i=0;i<Editor.sel2.size();i++){
((Triangle)Editor.sel2.elementAt(i)).smooth=false;
}
}
}
/**
* Called when a key is released.
*/
protected void keyReleased(int keyCode) {
}
/**
* Called when a key is repeated (held down).
*/
protected void keyRepeated(int keyCode) {
if(md==1){
switch(getGameAction(keyCode)){
case UP: if(mv)move(0,-5); else if(cy>=5)cy-=5;break;
case DOWN: if(mv)move(0,5); else if(cy<=h-55)cy+=5;break;
case RIGHT:if(mv)move(5,0); else if(cx<=w-15)cx+=5;break;
case LEFT:if(mv)move(-5,0); else if(cx>=5)cx-=5;break;
}
}
}
/**
* Called when the pointer is dragged.
*/
protected void pointerDragged(int x, int y) {
if(md==1&&mv){
move(x-xs,y-ys);
xs=x;
ys=y;
}
}
/**
* Called when the pointer is pressed.
*/
protected void pointerPressed(int xp, int yp) {
if(yp>=h-40){
if(xp<=w/4){
if(md>=1&&md<=3)toEdit(); else Main.main.toEditor();
}
else if(xp>=w-w/4){
if(md!=1)fire();
}
}
if(md!=1){
if(yp>h/3-modes.getHeight()/2){
int ti=m.getTouchIndex(yp);
if(ti!=0xffffff){
m.index=ti;
repaint();
fire();
}
}
if(yp<=h/3-modes.getHeight()/2){
if(xp-((w-modes.getWidth())/2)<=modes.getWidth()/3){
mo=0;
toEdit();
}
else if(xp-((w-modes.getWidth())/2)<=modes.getWidth()*2/3){
mo=1;
toEdit();
}
else if(xp-((w-modes.getWidth())/2)<=modes.getWidth()){
mo=2;
toEdit();
}
}
}
else{
int ld=Statics.font.stringWidth("Ok")+5;
if(xp>w-(w-ld-5)/2-5&&yp>=h-40){
tn--;
if(tn<0){if(MaterialEditor.mat!=null&&!MaterialEditor.mat.isEmpty())tn=MaterialEditor.mat.size(); else tn=0; }
updImg();
}
else if(xp>ld+(w-ld-5)/2&&yp>=h-40){
if(MaterialEditor.mat!=null&&!MaterialEditor.mat.isEmpty()){
tn++;
if(tn>MaterialEditor.mat.size())tn=0;
}
updImg();
}
else{
xs=xp;
ys=yp;
select(xp,yp);
}
}
}
/**
* Called when the pointer is released.
*/
protected void pointerReleased(int x, int y) {
if(md==1)
mv=false;
}
}

2038
src/Editor.java Normal file

File diff suppressed because it is too large Load Diff

1493
src/Face.java Normal file

File diff suppressed because it is too large Load Diff

411
src/FileMan.java Normal file
View File

@ -0,0 +1,411 @@
// Файловый менеджер, конечно
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import java.io.*;
import java.util.Enumeration;
import javax.microedition.io.*;
import javax.microedition.io.file.*;
import javax.microedition.lcdui.*;
/**
* @author Александр
*/
public class FileMan extends Canvas/* implements CommandListener */{
Menu m,sm;
String path;
int md,type,xs,ys; // 0 - open, 1 - save, 2 - texture, 3 - rendered image
Image imgtosave;
/**
* constructor
*/
public FileMan(int ty) {
setFullScreenMode(true);
path="/";
md=0;
type=ty;
m=new Menu(null,Statics.font);
if(type!=1&&type!=3)sm=new Menu(new String[]{Statics.russian?"Выбрать":"Select",Statics.russian?"Отмена":"Cancel"},Statics.font);
else sm=new Menu(new String[]{Statics.russian?"Выбрать":"Select",Statics.russian?"Новый файл":"New file",Statics.russian?"Отмена":"Cancel"},Statics.font);
setEnum(path);
/*try {
setCommandListener(this);
addCommand(new Command("Exit", Command.EXIT, 1));
} catch (Exception e) {
e.printStackTrace();
}*/
}
/**
* paint
*/
public void paint(Graphics g) {
g.setColor(Statics.menuBack);
g.fillRect(0, 0, Statics.w, Statics.h);
m.paint(g, 0, 0, Statics.w, Statics.h-40, 0);
if(md==0){
drawLeftSoft(g,Statics.russian?"Назад":"Back");
drawRightSoft(g,Statics.russian?"Опции":"Options");
}
if(md==1){
g.setColor(Statics.menuBack);
g.fillRect(Statics.w-Statics.font.stringWidth("Новый файл"), Statics.h-Statics.font.getHeight()*3, Statics.font.stringWidth("Новый файл"), Statics.font.getHeight()*3);
g.setColor(0x444444);
g.drawRect(Statics.w-Statics.font.stringWidth("Новый файл"), Statics.h-Statics.font.getHeight()*3, Statics.font.stringWidth("Новый файл"), Statics.font.getHeight()*3);
sm.paint(g, Statics.w-Statics.font.stringWidth("Новый файл"), Statics.h-Statics.font.getHeight()*3, Statics.font.stringWidth("Новый файл"), Statics.font.getHeight()*3, 2);
}
if(md==2){
g.setColor(Statics.menuBack);
g.fillRect(Statics.w/2-Statics.font.stringWidth("Перезаписать?")/2, Statics.h/2-30, Statics.font.stringWidth("Перезаписать?"), 60);
g.setColor(0x444444);
g.fillRect(Statics.w/2-Statics.font.stringWidth("Перезаписать?")/2, Statics.h/2-30, Statics.font.stringWidth("Перезаписать?"), 60);
g.setColor(Statics.textColor);
g.drawString(Statics.russian?"Перезаписать?":"Rewrite", Statics.w/2, Statics.h/2, 17);
drawLeftSoft(g,Statics.russian?"Да":"Yes");
drawRightSoft(g,Statics.russian?"Нет":"No");
}
}
private void drawLeftSoft(Graphics g,String s){
int sh=g.getFont().getHeight();
if(!Statics.touch){
g.setColor(8947967);
g.fillRoundRect(0, Statics.h - sh+1, g.getFont().stringWidth(s)+5, sh-1,10,10);
g.setColor(0);
g.drawRoundRect(0, Statics.h - sh+1, g.getFont().stringWidth(s)+5, sh-2,10,10);
g.setColor(0x555555);
g.drawString(s, 2, Statics.h - 2, 36);
g.setColor(Statics.textColor);
g.drawString(s, 3, Statics.h - 1, 36);}
else{
g.setColor(8947967);
g.fillRoundRect(0, Statics.h - 40, g.getFont().stringWidth(s)+5, 39,15,15);
g.setColor(0);
g.drawRoundRect(0, Statics.h - 40, g.getFont().stringWidth(s)+5, 38,15,15);
g.setColor(0x555555);
g.drawString(s, 2, Statics.h + sh/2 - 20, 36);
g.setColor(Statics.textColor);
g.drawString(s, 3, Statics.h +sh/2 - 19, 36);
}
}
private void drawRightSoft(Graphics g,String s){
int sh=g.getFont().getHeight();
if(!Statics.touch){
g.setColor(8947967);
g.fillRoundRect(Statics.w-g.getFont().stringWidth(s)-5, Statics.h - sh + 1, g.getFont().stringWidth(s)+5, sh-1,10,10);
g.setColor(0);
g.drawRoundRect(Statics.w-g.getFont().stringWidth(s)-5, Statics.h - sh + 1, g.getFont().stringWidth(s)+4, sh-2,10,10);
g.setColor(0x555555);
g.drawString(s, Statics.w - 4, Statics.h - 2, 40);
g.setColor(Statics.textColor);
g.drawString(s, Statics.w - 3, Statics.h - 1, 40);}
else{
g.setColor(8947967);
g.fillRoundRect(Statics.w-g.getFont().stringWidth(s)-5, Statics.h - 40, g.getFont().stringWidth(s)+5, 39,15,15);
g.setColor(0);
g.drawRoundRect(Statics.w-g.getFont().stringWidth(s)-5, Statics.h-40, g.getFont().stringWidth(s)+4, 38,15,15);
g.setColor(0x555555);
g.drawString(s, Statics.w - 4, Statics.h+sh/2- 20, 40);
g.setColor(Statics.textColor);
g.drawString(s, Statics.w - 3, Statics.h+sh/2 - 19, 40);
}
}
private void setEnum(String path){
Enumeration en=null;
try{
if(path.equals("/"))
en=FileSystemRegistry.listRoots();
else{
FileConnection fc=(FileConnection)Connector.open("file://"+path);
if(fc.exists())
en=fc.list();
fc.close();
}
}catch(Exception e){en=null;}
if(en!=null){
m.setElems(en,!path.equals("/"));
m.index=0;
}
}
/**
* Called when a key is pressed.
*/
protected void keyPressed(int key) {
String strCode = null;
try {
strCode = getKeyName(key).toLowerCase();
}
catch (IllegalArgumentException e) {
}
if (strCode != null)
{
if (("soft1".equals(strCode)) || ("soft 1".equals(strCode)) || ("soft_1".equals(strCode)) || ("softkey 1".equals(strCode)) || ("sk2(left)".equals(strCode)) || (strCode.startsWith("left soft"))){
left(); return; }
if (("soft2".equals(strCode)) || ("soft 2".equals(strCode)) || ("soft_2".equals(strCode)) || ("softkey 4".equals(strCode)) || ("sk1(right)".equals(strCode)) || (strCode.startsWith("right soft"))){
right(); return;}
}
switch (key)
{
case -202:
case -21:
case -6:
case 21:
case 105:
case 113:
case 57345:
left(); break;
case -203:
case -22:
case -7:
case 22:
case 106:
case 112:
case 57346:
right(); break;
}
int ga=getGameAction(key);
switch(ga){
case FIRE:
if(md==0||md==1&&sm.index==0){
md=0;
if(m.index==0&&!path.equals("/"))up();
else{
if((path+m.getSelestedName()).endsWith("/")){path=path+m.getSelestedName();
setEnum(path); }
else{
if(type==0)Main.main.menu.open(path+m.getSelestedName());
else if(type==1) md=2;
else if(type==2){
setMap(path+m.getSelestedName());
}
else if(type==3){
md=1;
sm.index=1;
right();
} }
}}
else right();
break;
case UP: if(md==0)m.up(); else if(md==1)sm.up();break;
case DOWN: if(md==0)m.down(); else if(md==1)sm.down();break;
}
repaint();
}
private void left(){
if(md==0)up();
else if(md==1){md=0; repaint(); }
else if(md==2)if(type==1)Main.main.menu.save(path+m.getSelestedName()); else{
md=1;
sm.index=1;
right();
}
}
private void up(){
if(path.equals("/")){
if(type==2)Main.main.d.setCurrent(Main.main.me);
else Main.main.toMenu();
}
int i=path.lastIndexOf('/',path.length()-2);
path=path.substring(0,i+1);
setEnum(path);
repaint();
}
private void right(){
if(md==0)md=1;
else if(md==1)switch(sm.index){
case 0: if(m.index==0&&!path.equals("/")){ md=0; up();}
else{
if((m.getSelestedName()).endsWith("/")){
path=path+m.getSelestedName();
setEnum(path); }
else{
if(type==0)Main.main.menu.open(path+m.getSelestedName());
else if(type==1) md=2;
else if(type==2){
setMap(path+m.getSelestedName());
}
else if(type==3){
md=1;
sm.index=1;
right(); } }
} break;
case 1: if(type==1||type==3){
//newfile
final TextBox tb=new TextBox(Statics.russian?"Имя файла":"File name",Main.main.e.name.equals("")?"model":Main.main.e.name,30,TextField.ANY);
Main.main.d.setCurrent(tb);
if(type==1)tb.addCommand(new Command("Ok",Command.OK,1));
else if(type==3){
tb.addCommand(new Command(Statics.russian?"Сохранить в Jpg":"Save as Jpg",Command.OK,1));
tb.addCommand(new Command(Statics.russian?"Сохранить в Png":"Save as Png",Command.OK,2));
tb.addCommand(new Command(Statics.russian?"Сохранить в Gif":"Save as Gif",Command.OK,3));
}
tb.addCommand(new Command(Statics.russian?"Отмена":"Cancel",Command.CANCEL,4));
tb.setCommandListener(new CommandListener(){
public void commandAction(Command com,Displayable d){
if(com.getPriority()<4){
String n=tb.getString();
String[] s=m.e;
boolean flag;
String ext="";
if(com.getPriority()==1)ext=type==1?".s3d":".jpg";
else if(com.getPriority()==2)ext=".png";
else if(com.getPriority()==3)ext=".gif";
int i=-1,j;
while(true){
i++;
flag=false;
for(j=0;j<s.length;j++){
if(s[j].equals(n+(i==0?"":"["+Integer.toString(i)+"]")+ext)&&!flag)flag=true;
}
if(!flag)break;
}
if(type==1)Main.main.menu.save(path+tb.getString()+(i==0?"":"["+Integer.toString(i)+"]")+ext);
else{
saveImage(com.getPriority(),path+tb.getString()+(i==0?"":"["+Integer.toString(i)+"]")+ext);
}
}
else Main.main.d.setCurrent(Main.main.fm);
}
});
}
else{
Main.main.toMenu();
} break;
case 2: Main.main.toMenu();break;
}
else if(md==2){
md=0;
}
repaint();
}
private void saveImage(int format,String url){
if(imgtosave==null)return;
try{
FileConnection fc=(FileConnection)Connector.open("file://"+url, Connector.READ_WRITE);
if(fc.exists())fc.delete();
fc.create();
OutputStream dos=fc.openDataOutputStream();
switch(format){
case 1: JpegEncoder je = new JpegEncoder(imgtosave, 100, dos); break;//jpg
case 2:byte[] barray=Encoder.toPNG(imgtosave); dos.write(barray); barray=null; break; //png
case 3: Lib_gif.init(100);
Lib_gif.add_frame(imgtosave);
Lib_gif.close(dos);//gif
}
dos.flush();
dos.close();
fc.close();
}catch(Exception e){}
Main.main.toEditor();
}
private void setMap(String p){
Image img=null;
try{
FileConnection fc=(FileConnection)Connector.open("file://"+p, Connector.READ);
if(!fc.exists())return;
InputStream is=fc.openInputStream();
img=Image.createImage(is);
is.close();
fc.close();
}catch(Exception e){}
if(img!=null){
Main.main.me.setMap(img);
Main.main.d.setCurrent(Main.main.me);
}
}
/**
* Called when a key is released.
*/
protected void keyReleased(int keyCode) {
}
/**
* Called when a key is repeated (held down).
*/
protected void keyRepeated(int keyCode) {
}
/**
* Called when the pointer is dragged.
*/
protected void pointerDragged(int x, int y) {
if(md==0){
m.move(y-ys);
ys=y;
repaint();
}
else{
}
}
/**
* Called when the pointer is pressed.
*/
protected void pointerPressed(int x, int y) {
if(md!=1){
if(x<=Statics.w/4&&y>=Statics.h-40)left();
else if(x>=Statics.w-Statics.w/4&&y>=Statics.h-40)right();
else{
/*int mi=m.getTouchIndex(y);
if(mi!=0xffffff)m.index=mi;
repaint();*/
xs=x;
ys=y;
}
}
else{
if(x>=Statics.w-Statics.font.stringWidth(Statics.russian?"Новый файл":"New File")){
int mi=sm.getTouchIndex(y);
if(mi!=0xffffff){
sm.index=mi;
right();
}
}
else{
md=0;
repaint();
}
}
}
/**
* Called when the pointer is released.
*/
protected void pointerReleased(int x, int y) {
int mi=m.getTouchIndex(y);
if(xs==x&&ys==y){
if(mi==m.index){
if(m.index==0&&!path.equals("/"))up();
else{
if(m.getSelestedName().endsWith("/")){
path=path+m.getSelestedName();
setEnum(path);} else{ if(type==0)Main.main.menu.open(path+m.getSelestedName()); else if(type==1)md=2; else if(type==2){
setMap(path+m.getSelestedName());
} }}
}
else m.index=mi;
}
repaint();
}
/**
* Called when action should be handled
*/
public void commandAction(Command command, Displayable displayable) {
}
}

237
src/Group.java Normal file
View File

@ -0,0 +1,237 @@
// класс для так называемых Групп - массивов полигонов, образующих отдельные объекты
import java.util.*;
import javax.microedition.lcdui.Graphics;
public class Group
{
public int ax,ay,az,maxx,maxy,maxz,minx,miny,minz;
public Vector f,v;
public String name="";
public boolean visible=true;
public Group(){
f=new Vector();
v=new Vector();
int id=0;
if(Main.main.e.m!=null)id=Main.main.e.m.g.size();
name="Group_"+id;
}
public Group(Face[] t,String n,int in){
f=new Vector();
v=new Vector();
if(t==null)return;
for(int i=0;i<t.length;i++){
Face fc=t[i];
f.addElement(fc);
if(fc instanceof Triangle){
Triangle tr=(Triangle)fc;
if(!v.contains(tr.a))v.addElement(tr.a);
if(!v.contains(tr.b))v.addElement(tr.b);
if(!v.contains(tr.c))v.addElement(tr.c);
}
else{
Line l=(Line)fc;
if(!v.contains(l.a))v.addElement(l.a);
if(!v.contains(l.b))v.addElement(l.b);
}
}
if(in>=0){verNorm();}
name=n+"_"+in;
}
public void triNorm(){ // нормали для треугольников
for (int i=0;i<f.size();i++){
if(f.elementAt(i) instanceof Triangle)
((Triangle)f.elementAt(i)).norm();}
}
public void verNorm(){ // рассчет нормалей для вершин
int nn;
for(int i=0;i<v.size();i++){
Vertex vv=(Vertex)v.elementAt(i);
nn=0;
for(int k=0;k<f.size();k++){
Triangle tr=(Triangle)f.elementAt(k);
if((vv==tr.a||vv==tr.b||vv==tr.c)&&tr.smooth){
nn++;
vv.nz+=tr.nz;
vv.nx+=tr.nx;
vv.ny+=tr.ny;
}
}
vv.nx/=nn;
vv.ny/=nn;
vv.nz/=nn;
}
}
public void countBoundary(){ // рассчет границ группы
maxx=minx=((Vertex)v.elementAt(0)).x;
maxy=miny=((Vertex)v.elementAt(0)).y;
maxz=minz=((Vertex)v.elementAt(0)).z;
ax=ay=az=0;
for(int i=0;i<v.size();i++){
Vertex ve=(Vertex)v.elementAt(i);
if(ve.x>maxx)maxx=ve.x;
if(ve.x<minx)minx=ve.x;
if(ve.y>maxy)maxy=ve.y;
if(ve.y<miny)miny=ve.y;
if(ve.z>maxz)maxz=ve.z;
if(ve.z<minz)minz=ve.z;
ax+=ve.x;
ay+=ve.y;
az+=ve.z;
}
ax/=v.size();
ay/=v.size();
az/=v.size();
}
public void draw(Graphics g,Matrix3D n,Vector l) { // плоская отрисовка
if(!visible)return;
for(int i=0;i<v.size();i++){
((Vertex)v.elementAt(i)).setMatrix(n);
}
for (int i = f.size() - 1; i >= 0; --i) {
if(f.elementAt(i) instanceof Triangle){
((Triangle)f.elementAt(i)).setMatrix(n);
if(((Triangle)f.elementAt(i)).isVisible(0)){
((Triangle)f.elementAt(i)).light(l);
((Triangle)f.elementAt(i)).paint(g,0);
}
}
else{
((Line)f.elementAt(i)).paint(g);
}
}
}
// shad: 0 - poly, 1 - smooth, 2 - flat, 3 - wire, 4 - bounding box
public void render(int[] r,int[] z,Matrix3D n,Vector l,int shad, int view) {
if(!visible)return;
if(shad!=4){ for(int i=0;i<v.size();i++){
Vertex ver=(Vertex)v.elementAt(i);
if(view==0)ver.setMatrix(n);
if(shad==1)ver.light(l);
if(Edit.mo==2){
for (int j=ver.sx-4;j<=ver.sx+4;j++){
for(int k=ver.sy-4;k<=ver.sy+4;k++){
if(j<Statics.w&&j>=0&&k<Statics.h&&k>=0){z[Statics.w*k+j]=(ver.zc-50)<<16;
r[Statics.w*k+j]=0x111177;
}
}
}
}
}
for (int i = f.size() - 1; i >= 0; --i) {
if(Editor.sel2!=null&&Editor.sel2.contains(f.elementAt(i))&&Edit.mo==1) continue;
if(f.elementAt(i) instanceof Triangle){
Triangle t=((Triangle)f.elementAt(i));
t.setMatrix(n);
if(t.isVisible(view)){
if((shad==1&&!t.smooth)||shad==0)t.light(l);
t.render(r,z,shad,view);}
}
else{
Line line=(Line)f.elementAt(i);
line.render(r, z,view);
}
}}
else{
Group gr=new Group(Create.wireBox(new Vertex(minx,miny,minz), new Vertex(maxx,maxy,maxz), 0xffffff),null,-1);
gr.render(r, z, n, null, 3,view);
}
}
public int[] getBounce(Matrix3D m){ // ограничивающий прямооугольник (2D)
int[] b=new int[5];
Vertex ve=(Vertex)v.firstElement();
ve.setMatrix(m);
b[0]=b[2]=ve.sx;
b[1]=b[3]=ve.sy;
b[4]=ve.zc;
for (int i=0;i<v.size();i++){
ve=(Vertex)v.elementAt(i);
ve.setMatrix(m);
if(ve.sx<b[0])b[0]=ve.sx;
if(ve.sy<b[1])b[1]=ve.sy;
if(ve.sx>b[2])b[2]=ve.sx;
if(ve.sy>b[3])b[3]=ve.sy;
if(ve.zc<b[4])b[4]=ve.zc;
}
return b;
}
public int[] getVolumeBounce(Matrix3D m){ // ограничивающий бокс (3D)
int[] b=new int[6];
Vertex ve=(Vertex)v.firstElement();
ve.setMatrix(m);
b[0]=b[3]=ve.x;
b[1]=b[4]=ve.y;
b[2]=b[5]=ve.z;
for (int i=0;i<v.size();i++){
ve=(Vertex)v.elementAt(i);
ve.setMatrix(m);
if(ve.x<b[0])b[0]=ve.x;
if(ve.y<b[1])b[1]=ve.y;
if(ve.z<b[2])b[2]=ve.z;
if(ve.x>b[3])b[3]=ve.x;
if(ve.y>b[4])b[4]=ve.y;
if(ve.z>b[5])b[5]=ve.z;
}
return b;
}
public boolean picking(int x,int y){ // проверка на попадание группы под курсор
boolean b=false;
for (int i=0;i<f.size();i++){
Face face=(Face)f.elementAt(i);
if(!b) b=face.picking(x, y);
}
return b;
}
public void soequal(Matrix3D m,int type){ // закрепление после трансформаций
for(int i=0;i<v.size();i++){
((Vertex)v.elementAt(i)).setMatrix(m);
((Vertex)v.elementAt(i)).soequal();
if(type==1){((Vertex)v.elementAt(i)).soeqNorm(); ((Vertex)v.elementAt(i)).normalize();}
}
if(type==1)for(int i=0;i<f.size();i++){
((Face)f.elementAt(i)).setMatrix(m);
((Face)f.elementAt(i)).soequal();
}
}
public void add(Face fc){ // добавить полигон в группу
f.addElement(fc);
if(fc instanceof Triangle){
Triangle tr=(Triangle)fc;
int in=findVertex(tr.a.x,tr.a.y,tr.a.z);
if(in==-1)v.addElement(tr.a); else tr.a=(Vertex)v.elementAt(in);
in=findVertex(tr.b.x,tr.b.y,tr.b.z);
if(in==-1)v.addElement(tr.b); else tr.b=(Vertex)v.elementAt(in);
in=findVertex(tr.c.x,tr.c.y,tr.c.z);
if(in==-1)v.addElement(tr.c); else tr.c=(Vertex)v.elementAt(in);
}
}
private int findVertex(int x,int y,int z){ // содержит ли группа вершину
for(int i=0;i<v.size();i++){
Vertex ver=(Vertex)v.elementAt(i);
if(ver.x==x&&ver.y==y&&ver.z==z)return i;
}
return -1;
}
public void setMaterial(Material m){ // установить материал
for(int i=0;i<f.size();i++){
if(f.elementAt(i) instanceof Triangle)
((Triangle)f.elementAt(i)).material=m;
}
}
public void deleteVertexSafety(Vertex v){
}
}

50
src/Ksort.java Normal file
View File

@ -0,0 +1,50 @@
// сортировка Шелла с предустановленными значениями длин промежутков самая быстрая при паре тысяч полигонов, а нам она нужны только при отрисовке малого количества полигонов
import java.util.Vector;
public class Ksort {
private static final int[] d = {1, 4, 10, 23, 57, 145, 356, 911, 1968, 4711, 11969, 27901, 84801, 213331, 543749, 1355339, 3501671, 8810089, 21521774, 58548857, 157840433, 410151271, 1131376761, 2147483647};
public static void sort(Vector e) {
Face temp=null;
int i=0, j=0, k=0, m = 0,s=e.size();
while(d[m] < s) ++m;
while(--m >= 0) {
k = d[m];
for(i=k; i<s; i++) { // k-сортировка
j = i;
temp = (Face)e.elementAt(i);
int tmpsz=temp.getS();
while( (j >= k) && (((Face)e.elementAt(j-k)).getS() > tmpsz) ) {
e.setElementAt(e.elementAt(j - k),j);
j -= k;
}
e.setElementAt(temp,j);
}
}
}
public static void sort(Face[] e) {
Face temp=null;
int i=0, j=0, k=0, m = 0,s=e.length,tmpsz;
while(d[m] < s) ++m;
while(--m >= 0) {
k = d[m];
for(i=k; i<s; i++) { // k-сортировка
j = i;
temp = e[i];
if(temp==null)temp=new Triangle(new Vertex(),new Vertex(),new Vertex(),0);
tmpsz=temp.getS();
while( (j >= k) && ((e[j-k]).getS() > tmpsz) ) {
e[j]=e[j - k];
j -= k;
}
e[j]=temp;
}
}
}
}

34
src/Light.java Normal file
View File

@ -0,0 +1,34 @@
/**
* Точка всенаправленного источника света.
* @author Shaman
*/
public class Light {
public int x, y, z, xc, yc, zc, sx, sy;
public float s = 1;
public Light(int a, int b, int c) {
xc = x = a;
yc = y = b;
zc = z = c;
}
public Light(Vertex v) {
xc = x = v.x;
yc = y = v.y;
zc = z = v.z;
}
public void setMatrix(Matrix3D m) {
xc = (int) (x * m.xx + y * m.xy + z * m.xz);
yc = (int) (x * m.yx + y * m.yy + z * m.yz);
zc = (int) (x * m.zx + y * m.zy + z * m.zz);
xc += (int) m.xo;
yc += (int) m.yo;
zc += (int) m.zo;
int z2 = (zc > -Vertex.dist + 1) ? zc : -Vertex.dist + 1;
z2 += Vertex.dist;
sx = (Statics.w / 2 + xc * Statics.pers / z2);
sy = (Statics.h / 2 - yc * Statics.pers / z2);
}
}

101
src/Line.java Normal file
View File

@ -0,0 +1,101 @@
import javax.microedition.lcdui.Graphics;
public class Line extends Face
{
public Vertex a;
public Vertex b;
public Line(Vertex v1, Vertex v2, int col)
{
a = v1;
b = v2;
color = col;}
public int getS() {
return ((a.zc + b.zc) / 2); }
public void paint(Graphics g) {
paint(g, color); }
public void setVertexMatrix(Matrix3D m) {
a.setMatrix(m);
b.setMatrix(m);
}
public void render(int r[],int z[]){
if(a.zc<-Vertex.dist&&b.zc<-Vertex.dist) return;
if(a.zc>Statics.limit&&b.zc>Statics.limit) return;
if(a.zc<-Vertex.dist){
int xc=a.xc + (b.xc - a.xc) * (-Vertex.dist - a.zc) / (b.zc - a.zc);
int yc=a.yc + (b.yc - a.yc) * (-Vertex.dist - a.zc) / (b.zc - a.zc);
a.xc=xc;
a.yc=yc;
a.zc=-Vertex.dist+1;
a.to2d();
}
if(b.zc<-Vertex.dist){
int xc=b.xc + (a.xc - b.xc) * (-Vertex.dist+1 - b.zc) / (a.zc - b.zc);
int yc=b.yc + (a.yc - b.yc) * (-Vertex.dist+1 - b.zc) / (a.zc - b.zc);
b.xc=xc;
b.yc=yc;
b.zc=-Vertex.dist+1;
b.to2d();
}
if(a.sx<0&&b.sx<0)return;
if(a.sy<0&&b.sy<0)return;
if(a.sx>Statics.w&&b.sx>Statics.w)return;
if(a.sy>Statics.h&&b.sy>Statics.h)return;
drawLine(r,a.sx,a.sy,b.sx,b.sy,color);
}
public void render(int[] r,int[] z,int v){
double scale=0;
if(v!=0){
scale=(double)Main.main.e.dist;
if(scale>0)scale=scale/10000+0.1;
else if(scale==0)scale=0.1;
else scale=0.1+scale/100000;}
if(v==0)render(r,z);
else if(v==1){
int x0=Main.main.e.xo;
int z0=Main.main.e.zo;
drawLine(r,(int)(Statics.w/2+a.x*scale+x0*scale),(int)(Statics.h/2-a.z*scale-z0*scale),(int)(Statics.w/2+x0*scale+b.x*scale),(int)(Statics.h/2-b.z*scale-z0*scale),color);}
else if(v==2){
int y0=Main.main.e.yo;
int z0=Main.main.e.zo;
drawLine(r,(int)(Statics.w/2+z0*scale+a.z*scale),(int)(Statics.h/2-y0*scale-a.y*scale),(int)(Statics.w/2+z0*scale+b.z*scale),(int)(Statics.h/2-y0*scale-b.y*scale),color);
}
else if(v==3){
int y0=Main.main.e.yo;
int x0=Main.main.e.xo;
drawLine(r,(int)(Statics.w/2+x0*scale+a.x*scale),(int)(Statics.h/2-y0*scale-a.y*scale),(int)(Statics.w/2+x0*scale+b.x*scale),(int)(Statics.h/2-y0*scale-b.y*scale),color);
}
}
public void paint(Graphics g, int col) {
if(a.zc<-Vertex.dist&&b.zc<-Vertex.dist) return;
if(a.zc>Statics.limit&&b.zc>Statics.limit) return;
if(a.zc<-Vertex.dist){
int xc=a.xc + (b.xc - a.xc) * (-Vertex.dist - a.zc) / (b.zc - a.zc);
int yc=a.yc + (b.yc - a.yc) * (-Vertex.dist - a.zc) / (b.zc - a.zc);
a.xc=xc;
a.yc=yc;
a.zc=-Vertex.dist+1;
a.to2d();
}
if(b.zc<-Vertex.dist){
int xc=b.xc + (a.xc - b.xc) * (-Vertex.dist+1 - b.zc) / (a.zc - b.zc);
int yc=b.yc + (a.yc - b.yc) * (-Vertex.dist+1 - b.zc) / (a.zc - b.zc);
b.xc=xc;
b.yc=yc;
b.zc=-Vertex.dist+1;
b.to2d();
}
if(a.sx<0&&b.sx<0)return;
if(a.sy<0&&b.sy<0)return;
if(a.sx>Statics.w&&b.sx>Statics.w)return;
if(a.sy>Statics.h&&b.sy>Statics.h)return;
g.setColor(col);
g.drawLine(a.sx, a.sy, b.sx, b.sy);
}
}

505
src/Loader.java Normal file
View File

@ -0,0 +1,505 @@
// загрузчик моделей s3d, obj и wax из файлов. Wax бывает не корректен из-за группированных объектов, которые здесь не поддерживаются
/*
* To change this template, choose Tools | Templates and open the template in
* the editor.
*/
import java.io.*;
import java.util.Vector;
import javax.microedition.io.*;
import javax.microedition.io.file.*;
import javax.microedition.lcdui.Image;
/**
*
* @author Shaman
*/
public class Loader {
int p;
public Loader(){
}
public Model openWax(InputStream ist){
Model m=new Model();
Matrix3D n=Main.main.e.n;
String s=" ";
try{
DataInputStream is=new DataInputStream(ist);
byte[] b=new byte[is.available()];
is.read(b);
s=new String(b);
is.close();
double[] in;
while(p>=0){
p=s.indexOf("<object",p);
if(p<0)break;
int k=s.indexOf('"',p);
int k1=s.indexOf('"', k+1);
String obj=s.substring(k+1, k1);
if(!obj.equals("sphere")&&!obj.equals("cylinder")&&!obj.equals("box")){p++; continue;}
k=s.indexOf('"',k1+1);
k1=s.indexOf('"', k+1);
in=getNums(s.substring(k+1, k1)); //location
float xo=(float)(in[0]*200),yo=(float)(in[1]*200),zo=(float)(in[2]*200);
k=s.indexOf('"',k1+1);
k1=s.indexOf('"', k+1);
in=getNums(s.substring(k+1, k1)); // rotation
double x=in[0],y=in[1],z=in[2];
k=s.indexOf('"',k1+1);
k1=s.indexOf('"', k+1);
in=getNums(s.substring(k+1, k1)); // scale
double xs=in[0],ys=in[1],zs=in[2];
k=s.indexOf('"',k1+1);
k1=s.indexOf('"', k+1);
int[] inn=getNumms(s.substring(k+1, k1)); // color
if(obj.equals("sphere")){
m.add(Create.sphere(new Vertex(0,0,0), 500, 7, 7, (inn[0]<<16)|(inn[1]<<8)|(inn[2])), obj);
}
else if(obj.equals("cylinder")){
m.add(Create.cylinder(new Vertex(0,-500,0), 500, 1000, 10, (inn[0]<<16)|(inn[1]<<8)|(inn[2])), obj);
}
else if(obj.equals("box")){
m.add(Create.box(new Vertex(-500,-500,500), new Vertex(500,500,-500), ((inn[0]<<16)|(inn[1]<<8)|(inn[2]))), obj);
}
else{p++; continue;
}
if(!m.g.isEmpty()){
Group gr=m.getLast();
n.unit();
n.scale((float)xs,(float)ys, (float)zs);
n.yrot(y);
n.xrot(x);
n.zrot(z);
n.translate(-xo, yo, zo);
gr.soequal(n,1);
gr.countBoundary();
}
p++;
}
}catch(Exception e){return m;
}
return m;
}
private double[] getNums(String s){
try{
double[] ret=new double[3];
int pos1=0,pos=s.indexOf(',');
ret[0]=Double.parseDouble(s.substring(pos1, pos-1));
pos1=s.indexOf(',',pos+1);
ret[1]=Double.parseDouble(s.substring(pos+1, pos1-1));
ret[2]=Double.parseDouble(s.substring(pos1+1));
//f.append(""+ret[0]+","+ret[1]+","+ret[2]+"; ");
return ret;
}catch(Exception e){
}
//f.append("ошибка; ");
return new double[]{0,0,0};
}
private int[] getNumms(String s){
int[] ret=new int[3];
int pos1=0,pos=s.indexOf(',');
ret[0]=Integer.parseInt(s.substring(pos1, pos));
pos1=s.indexOf(',',pos+1);
ret[1]=Integer.parseInt(s.substring(pos+1, pos1));
ret[2]=Integer.parseInt(s.substring(pos1+1));
return ret;
}
public Model loadObj(InputStream is){
Model m=new Model();
boolean vt=false,vn=false,readFace=false;
int vert=0;
Vector uv=new Vector();
Vector vno=new Vector();
Group gr=new Group();
try{
//InputStream is=getClass().getResourceAsStream("/file.txt");
DataInputStream dis=new DataInputStream(is);
byte by;
while(dis.available()>0){
by=dis.readByte();
if(by=='v'){
byte b=dis.readByte();
if(b==' '){
if(readFace){m.add(gr); gr.countBoundary();gr.triNorm(); if(!vn){gr.verNorm(); } vert+=gr.v.size(); gr=new Group(); readFace=false;vt=false;vn=false; }
readVertexInfo(dis,gr); }
else{
byte b1=dis.readByte();
if(b1==' '){
if(b=='t'){if(!vt)vt=true; readUVInfo(dis,uv);}
else if(b=='n'){if(!vn)vn=true;readNormInfo(dis,vno); }
}
}
}
else if(by=='f'){if(dis.readByte()==' '){if(!readFace)readFace=true; readFaceInfo(dis,gr,uv,vno,vn,vt,vert); }}
else if(by=='g'){if(dis.readByte()==' '){String st=new String(); while(by!=10&&by!=13){by=dis.readByte();st=st+(char)by;} gr.name=st; } }
else{ while(by!=10&&by!=13&&dis.available()>0) by=dis.readByte(); }
}
if(gr.v.size()>0&&gr.f.size()>0){m.add(gr); gr.triNorm(); if(!vn)gr.verNorm(); gr.countBoundary(); }
dis.close();
}catch(Exception e){return m;
}
return m;
}
public void readVertexInfo(DataInputStream dis,Group gr) throws IOException{
byte b=dis.readByte();
String s=new String();
while(b==' ')
b=dis.readByte();
while(b!=' '){
if((char)b>='0'&&(char)b<='9'||b=='-'||b=='.')s=s+(char)b;
b=dis.readByte();
}
float xx;
if(s.length()>0) xx=Float.parseFloat(s); else xx=0f;
while(b==' ')
b=dis.readByte();
s=new String();
while(b!=' '){
if((char)b>='0'&&(char)b<='9'||b=='-'||b=='.')s=s+(char)b;
b=dis.readByte();
}
float yy;
if(s.length()>0) yy=Float.parseFloat(s); else yy=0f;
while(b==' ')
b=dis.readByte();
s=new String();
while(b!='\n'){
if((char)b>='0'&&(char)b<='9'||b=='-'||b=='.')s=s+(char)b;
b=dis.readByte();
}
float zz;
if(s.length()>0)zz=Float.parseFloat(s); else zz=0f;
Vertex v3f=new Vertex((int)(xx*10),(int)(yy*10),(int)(zz*10));
gr.v.addElement(v3f);
}
//texture coordinates
public void readUVInfo(DataInputStream dis,Vector uv) throws IOException{
String s=new String();
byte b=dis.readByte();
while(b==' ')
b=dis.readByte();
while(b!=' '){
if((char)b>='0'&&(char)b<='9'||b=='-'||b=='.')s=s+(char)b;
b=dis.readByte();
}
Float uu;
if(s.length()>0) uu=new Float(Float.parseFloat(s)); else uu=new Float(0f);
while(b==' ')
b=dis.readByte();
s=new String();
while(b!=' '&&b!='\n'&&b!='\r'){
if((char)b>='0'&&(char)b<='9'||b=='-'||b=='.')s=s+(char)b;
b=dis.readByte();
}
Float vv;
if(s.length()>0) vv=new Float(Float.parseFloat(s)); else vv=new Float(0f);
uv.addElement(uu);
uv.addElement(vv);
}
public void readNormInfo(DataInputStream dis,Vector v) throws IOException{
byte b=dis.readByte();
String s=new String();
while(b==' ')
b=dis.readByte();
while(b!=' '){
if((char)b>='0'&&(char)b<='9'||b=='-'||b=='.')s=s+(char)b;
b=dis.readByte();
}
Float xx;
if(s.length()>0) xx=new Float(Float.parseFloat(s)); else xx=new Float(0f);
v.addElement(xx);
while(b==' ')
b=dis.readByte();
s=new String();
while(b!=' '){
if((char)b>='0'&&(char)b<='9'||b=='-'||b=='.')s=s+(char)b;
b=dis.readByte();
}
Float yy;
if(s.length()>0) yy=new Float(Float.parseFloat(s)); else yy=new Float(0f);
v.addElement(yy);
while(b==' ')
b=dis.readByte();
s=new String();
while(b!='\n'){
if((char)b>='0'&&(char)b<='9'||b=='-'||b=='.')s=s+(char)b;
b=dis.readByte();
}
Float zz;
if(s.length()>00) zz=new Float(Float.parseFloat(s)); else zz=new Float(0f);
v.addElement(zz);
}
//polygons
public void readFaceInfo(DataInputStream dis,Group gr,Vector uv,Vector vno,boolean vn,boolean vt,int vert) throws IOException{
Vector f=new Vector();
byte b=dis.readByte();
while(b!='\n'&&b!='\r'&&dis.available()>0){
String s=new String();
if(b==' '){
while(b==' '){
//if(dis.available()<=0)break;
b=dis.readByte();}}
else if(b=='/'){while(b=='/')b=dis.readByte();}
while(b!=' '&&b!='/'&&b!='\n'&&b!='\r'){
if((char)b>='0'&&(char)b<='9')s=s+(char)b;
//if(dis.available()<=0)break;
if(dis.available()>0)b=dis.readByte();
}
if(s.length()>0){Integer ind=new Integer(Integer.parseInt(s));
f.addElement(ind);}
//if(b=='\n'||b=='\r'||dis.available()<=0)break;
}
if(!vn&&!vt){
for(int i=1;i<=f.size()-2;i++)
gr.add(new Triangle((Vertex)gr.v.elementAt(((Integer)f.elementAt(0)).intValue()-vert-1),(Vertex)gr.v.elementAt(((Integer)f.elementAt(i)).intValue()-vert-1),(Vertex)gr.v.elementAt(((Integer)f.elementAt(i+1)).intValue()-vert-1),0xffffff));
}
else if(vn^vt){
for(int i=0; i<f.size()-4;i+=2){
Triangle t=new Triangle((Vertex)gr.v.elementAt(((Integer)f.elementAt(0)).intValue()-vert-1),(Vertex)gr.v.elementAt(((Integer)f.elementAt(i+2)).intValue()-vert-1),(Vertex)gr.v.elementAt(((Integer)f.elementAt(i+4)).intValue()-vert-1),0xffffff);
gr.add(t);
//f.addElement(new Integer(100500));
if(vn){
t.a.nx=((Float)vno.elementAt((((Integer)f.elementAt(1)).intValue()-1)*3)).floatValue();
t.a.ny=((Float)vno.elementAt((((Integer)f.elementAt(1)).intValue()-1)*3+1)).floatValue();
t.a.nz=((Float)vno.elementAt((((Integer)f.elementAt(1)).intValue()-1)*3+2)).floatValue();
t.b.nx=((Float)vno.elementAt((((Integer)f.elementAt(i+3)).intValue()-1)*3)).floatValue();
t.b.ny=((Float)vno.elementAt((((Integer)f.elementAt(i+3)).intValue()-1)*3+1)).floatValue();
t.b.nz=((Float)vno.elementAt((((Integer)f.elementAt(i+3)).intValue()-1)*3+2)).floatValue();
t.c.nx=((Float)vno.elementAt((((Integer)f.elementAt(i+5)).intValue()-1)*3)).floatValue();
t.c.ny=((Float)vno.elementAt((((Integer)f.elementAt(i+5)).intValue()-1)*3+1)).floatValue();
t.c.nz=((Float)vno.elementAt((((Integer)f.elementAt(i+5)).intValue()-1)*3+2)).floatValue();
t.norm((t.a.nx+t.b.nx+t.c.nx)/3,(t.a.ny+t.b.ny+t.c.ny)/3,(t.a.ny+t.b.ny+t.c.ny)/3);
t.setUV();
}
else{
t.uv=new float[]{((Float)uv.elementAt((((Integer)f.elementAt(1)).intValue()-1)*2)).floatValue(),((Float)uv.elementAt((((Integer)f.elementAt(1)).intValue()-1)*2+1)).floatValue(),((Float)uv.elementAt((((Integer)f.elementAt(i+3)).intValue()-1)*2)).floatValue(),((Float)uv.elementAt((((Integer)f.elementAt(i+3)).intValue()-1)*2+1)).floatValue(),((Float)uv.elementAt((((Integer)f.elementAt(i+5)).intValue()-1)*2)).floatValue(),((Float)uv.elementAt((((Integer)f.elementAt(i+5)).intValue()-1)*2+1)).floatValue()};
}
}
}
else if(vn&&vt){
for(int i=1;i<=f.size()/3-2;i+=3){
Triangle t=new Triangle((Vertex)gr.v.elementAt(((Integer)f.elementAt(0)).intValue()-vert-1),(Vertex)gr.v.elementAt(((Integer)f.elementAt(i+2)).intValue()-vert-1),(Vertex)gr.v.elementAt(((Integer)f.elementAt(i+5)).intValue()-vert-1),0xffffff);
gr.add(t);
//t.a.nx=()
}
}
}
public Model loadResourceAsS3D(String s){
try{
InputStream is=getClass().getResourceAsStream(s);
Model mod = loadS3D(is);
is.close();
return mod;
}catch(Exception e){ Model mod=new Model(); mod.add(Create.disk(new Vertex(0,0,0), 500, 30, 0x008800), "null"); return mod; }
}
public Model loadS3D(InputStream is){
try{
DataInputStream d=new DataInputStream(is);
int chunk=d.readInt();
if (chunk==0xffff06)return loadS3D06(d);
else return loadS3D05(d,chunk);
}catch(Exception e){return null; }
}
public Model loadS3D05(DataInputStream d,int numFaces){
Model mod=new Model();
Group m=new Group();
try{
int type;
for(int i=0;i<numFaces;i++){
type=d.readInt();
switch(type){
case 0: readTriangle(d,m);break;
case 1: readSquare(d,m);break;
case 2: readCircle(d,m);break;
case 3: readLine(d,m);break;
}
}
Material mat=new Material();
mat.doubleSided=true;
mat.useFaceColor=true;
m.countBoundary();
m.verNorm();
mod.add(m);
mod.setMaterial(mat);
MaterialEditor.mat.addElement(mat);
d.close();
}catch(Exception e){
mod.add(Create.disk(new Vertex(0,0,0), 500, 30, 0x008800), "null");
}
return mod;
}
public void readTriangle(DataInputStream d,Group m){
try{
Triangle f=new Triangle(nv(d),nv(d),nv(d),d.readInt());
f.smooth=false;
f.norm();
//f.invert();
m.add(f);
//f=null;
}catch(Exception e){}
}
public void readSquare(DataInputStream d,Group m){
try{
Vertex v1=nv(d);
Vertex v2=nv(d);
Vertex v3=nv(d);
Vertex v4=nv(d);
int col=d.readInt();
Triangle tr=new Triangle(v4,v2,v1,col);
Triangle tr2=new Triangle(v4,v3,v2,col);
tr.smooth=false;
tr2.smooth=false;
tr.norm();
//tr.invert();
tr2.norm();
//tr2.invert();
m.add(tr);
m.add(tr2);
}catch(Exception e){}
}
public void readCircle(DataInputStream d,Group m){
try{
Vertex v1=nv(d);
Vertex v2=nv(d);
Vertex v=new Vertex((v1.x+v2.x)/2,(v1.y+v2.y)/2,(v1.z+v2.z)/2);
int col=d.readInt();
Face[] f=Create.disk(v, Math.sqrt((v.x-v2.x)*(v.x-v2.x)+(v.y-v2.y)*(v.y-v2.y)+(v.z-v2.z)*(v.z-v2.z)), 30, col);
//Circle c=new Circle(nv(d),nv(d),d.readInt());
for(int i=0;i<f.length;i++)
m.add(f[i]);
}catch(Exception e){}
}
public void readLine(DataInputStream d,Group m){
try{
nv(d);
nv(d);
d.readInt();
//Line l=new Line(nv(d),nv(d),d.readInt());
//m.add(l);
}catch(Exception e){}
}
public Vertex nv(DataInputStream d){
try{
return new Vertex(d.readInt()*10,d.readInt()*10,d.readInt()*10);
}catch(Exception e){return null;}
}
public Model loadS3D06(DataInputStream d){
Model m=new Model();
int i,j;
try{
Main.main.e.name=new String();
j=d.readInt();
for(i=0;i<j;i++)
Main.main.e.name=Main.main.e.name+d.readChar();
Main.main.e.vendor=new String();
j=d.readInt();
for(i=0;i<j;i++)
Main.main.e.vendor=Main.main.e.vendor+d.readChar();
Main.main.e.description=new String();
j=d.readInt();
for(i=0;i<j;i++)
Main.main.e.description=Main.main.e.description+d.readChar();
int numMat=d.readInt();
int numObj=d.readInt();
int numLights=d.readInt();
Statics.background=d.readInt();
Statics.pers=d.readInt();
Statics.limit=d.readInt();
for(i=0;i<numMat;i++){
Material mat=new Material();
MaterialEditor.mat.addElement(mat);
int descLength=d.readInt();
String desc="";
for(j=0;j<descLength;j++)
desc=desc+d.readChar();
mat.desc=desc;
mat.diffuseColor=d.readInt();
mat.opacity=d.readInt();
mat.doubleSided=d.readBoolean();
mat.useFaceColor=d.readBoolean();
mat.self=d.readFloat();
mat.us=d.readFloat();
mat.vs=d.readFloat();
mat.uo=d.readFloat();
mat.vo=d.readFloat();
if(d.readBoolean()){
mat.w=d.readInt();
mat.h=d.readInt();
mat.texture=new int[mat.w*mat.h];
int MD=d.readInt();
int texlength=d.readInt();
if(MD!=2){
byte[] b=new byte[texlength];
d.read(b, 0, texlength);
Image im=Image.createImage(b, 0, texlength);
im.getRGB(mat.texture, 0, im.getWidth(), 0, 0, im.getWidth(), im.getHeight());
}
else for(j=0;j<texlength;j++){
//mat.texture[j]=(d.readByte()<<16)|(d.readByte()<<8)|d.readByte();
mat.texture[j]=d.readInt();
}
}
}
for(i=0;i<numObj;i++){
Group g=new Group();
int numchars=d.readInt();
g.name="";
for(j=0;j<numchars;j++)
g.name=g.name+d.readChar();
g.visible=d.readBoolean();
int numverts=d.readInt();
for(j=0;j<numverts;j++){
Vertex v=new Vertex(d.readInt(),d.readInt(),d.readInt());
g.v.addElement(v);
v.nx=d.readFloat();
v.ny=d.readFloat();
v.nz=d.readFloat();
}
int numfaces=d.readInt();
for(j=0;j<numfaces;j++){
Triangle t=new Triangle((Vertex)g.v.elementAt(d.readInt()),(Vertex)g.v.elementAt(d.readInt()),(Vertex)g.v.elementAt(d.readInt()),d.readInt());
g.f.addElement(t);
t.nx=d.readFloat();
t.ny=d.readFloat();
t.nz=d.readFloat();
t.smooth=d.readBoolean();
int mnum=d.readInt();
if(mnum>=0){
t.material=(Material)MaterialEditor.mat.elementAt(mnum);
}
if(d.readBoolean()){
t.uv=new float[6];
t.uv[0]=d.readFloat();
t.uv[1]=d.readFloat();
t.uv[2]=d.readFloat();
t.uv[3]=d.readFloat();
t.uv[4]=d.readFloat();
t.uv[5]=d.readFloat();
}
}
g.countBoundary();
m.add(g);
}
for(i=0;i<numLights;i++){
Light l=new Light(d.readInt(),d.readInt(),d.readInt());
m.l.addElement(l);
}
d.close();
}catch(Exception e){/*m.add(Create.disk(new Vertex(), 500, 30, 0xff00),"");*/
javax.microedition.lcdui.Form form=new javax.microedition.lcdui.Form("");
form.append("это капец бля(( "+e.toString());
Main.main.d.setCurrent(form);
}
return m;
}
}

422
src/Main.java Normal file
View File

@ -0,0 +1,422 @@
// главкласс, стартАпп. Инициализация, смена окон и настройки
import java.io.*;
import javax.microedition.io.*;
import javax.microedition.io.file.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.rms.RecordStore;
public class Main extends MIDlet
{
Display d;
MainMenu menu;
Editor e;
Edit edit;
Color color;
MaterialEditor me;
StartWindow st;
FileMan fm;
public static Main main;
public void startApp()
{
main = this;
d = Display.getDisplay(this);
if(!openSet())toMenu();
else{
st=new StartWindow();
d.setCurrent(st);}
}
public void newEditor() {
if(e!=null){
e.m=null;
e.n=null;
e.zb=null;
e.rgb=null;
e.zb2=null;
e.rgb2=null;
e.ver1=e.ver2=e.cur=null;
e.modes=null;
e.instrs=null;
e.instr=null;
e.innames=null;
e.buf=null;
e.gr=null;
Edit.mo=0;
Statics.background=0;
Statics.pers=300;
Statics.limit=20000;
e.sel=null;
e.sel2=null;
e.sel3=null;
e=null;
MaterialEditor.mat=null;
}
System.gc();
MaterialEditor.mat=new java.util.Vector();
e = new Editor();
}
public void toEditor() {
if(e==null)newEditor();
e.resetTimer();
e.render();
e.draw();
d.setCurrent(e); menu=null;edit=null;color=null;me=null;fm=null;System.gc();}
public void toMenu() {
if(menu==null){menu=new MainMenu();
menu.toMenu();}
d.setCurrent(menu);
color=null;
st=null;
fm=null;
}
public void toMatEd(){
me=new MaterialEditor();
d.setCurrent(me);
}
public void toEdit(){
edit=new Edit();
d.setCurrent(edit);
}
public void toOpen(){
fm=new FileMan(0);
d.setCurrent(fm);
}
public void toSave(){
fm=new FileMan(1);
d.setCurrent(fm);
}
public void toSaveRender(){
fm=new FileMan(3);
fm.imgtosave=Image.createRGBImage(e.rgb, Statics.w, Statics.h, false);
d.setCurrent(fm);
}
public void toOpenMap(){
fm=new FileMan(2);
d.setCurrent(fm);
}
public void toColor(){
color=new Color();
d.setCurrent(color);
}
public void setColor(int mode){
int fcol=0;
switch(mode){
case 1: fcol=Statics.edBack;break;
case 2: fcol=Statics.curColor;break;
case 3: fcol=Statics.gridColor;break;
case 4: fcol=Statics.menuBack;break;
case 5: fcol=Statics.textColor;break;
case 6: fcol=Statics.menuTextColor;break;
case 7: fcol=Statics.background;break;
}
color=new Color();
d.setCurrent(color);
color.mode=mode;
color.setColor(fcol);
}
public void resetView(){
e.x=20;
e.y=40;
e.z=0;
e.xo=0;
e.yo=0;
e.zo=0;
e.dist=0;
e.shading=1;
e.act=0;
e.view=0;
toEditor();
}
public void saveScreen(final Image i){
final TextBox tf=new TextBox("saving screenshot","file:///E:/1.gif",1000,TextField.ANY);
d.setCurrent(tf);
tf.addCommand(new Command("Ok",Command.OK,1));
tf.setCommandListener(new CommandListener() {
public void commandAction(Command c,Displayable dis){
try{
FileConnection fc=(FileConnection)Connector.open(tf.getString(),Connector.READ_WRITE);
if(fc.exists()){
fc.close();
fc=(FileConnection)Connector.open(tf.getString()+".gif",Connector.READ_WRITE);
}
fc.create();
OutputStream os=fc.openOutputStream();
Lib_gif.init(100);
Lib_gif.add_frame(i);
Lib_gif.close(os);
if(os!=null){os.close();os=null;}
if(fc!=null){fc.close();fc=null;}
toEditor();
}catch(Exception e){
Form ferr=new Form("error!");
ferr.append(e.getMessage()+"; "+e.toString());
ferr.addCommand(new Command("okay",Command.OK,1));
d.setCurrent(ferr);
ferr.setCommandListener(new CommandListener(){
public void commandAction(Command c,Displayable dis){
toEditor();
}
});
}
}
});
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
saveSet();
notifyDestroyed();
}
public boolean openSet(){
String rsname="S3DEditor 0.6";
RecordStore rs;
try{
rs=RecordStore.openRecordStore(rsname,true);
if(rs.getNumRecords()==0)return true;
}catch(Exception e){ rs=null; return true;
}
if(rs!=null){
try{
if(rs.getRecord(1)==null)return true;
DataInputStream dis=new DataInputStream(new ByteArrayInputStream(rs.getRecord(1)));
//Main.main.isFirst=dis.readBoolean();
Statics.russian=dis.readBoolean();
Statics.grid=dis.readBoolean();
Statics.extraBuffers=dis.readBoolean();
Statics.bigImages=dis.readBoolean();
Statics.touch=dis.readBoolean();
Statics.randColor=dis.readBoolean();
Statics.limit=dis.readInt();
Statics.pers=dis.readInt();
Statics.menuBack=dis.readInt();
Statics.edBack=dis.readInt();
Statics.curColor=dis.readInt();
Statics.textColor=dis.readInt();
Statics.gridColor=dis.readInt();
Statics.menuTextColor=dis.readInt();
Statics.background=dis.readInt();
Statics.font=Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, dis.readInt());
dis.close();
rs.closeRecordStore();
}catch(Exception e2){return true; }
}
return false;
}
public void saveSet(){
RecordStore rs=null;
String rsname="S3DEditor 0.6";
byte[] options=null;
try{
rs=RecordStore.openRecordStore(rsname,true);
ByteArrayOutputStream baos=new ByteArrayOutputStream();
DataOutputStream dos=new DataOutputStream(baos);
dos.writeBoolean(Statics.russian);
dos.writeBoolean(Statics.grid);
dos.writeBoolean(Statics.extraBuffers);
dos.writeBoolean(Statics.bigImages);
dos.writeBoolean(Statics.touch);
dos.writeBoolean(Statics.randColor);
dos.writeInt(Statics.limit);
dos.writeInt(Statics.pers);
dos.writeInt(Statics.menuBack);
dos.writeInt(Statics.edBack);
dos.writeInt(Statics.curColor);
dos.writeInt(Statics.textColor);
dos.writeInt(Statics.gridColor);
dos.writeInt(Statics.menuTextColor);
dos.writeInt(Statics.background);
dos.writeInt(Statics.font.getSize());
dos.flush();
options=baos.toByteArray();
dos.close();
baos.close();
rs.setRecord(1,options,0,options.length);
}catch(Exception e){
try{
rs.addRecord(options,0,options.length);
}catch(Exception e2){}
}
try{
rs.closeRecordStore();
rs=null;
}catch(Exception e){}
}
public static Image resizeImage(Image oldImage,int newW,int newH){
int oldW = oldImage.getWidth();
int oldH = oldImage.getHeight();
int[] pixels = new int[oldW*oldH];
oldImage.getRGB(pixels,0,oldW,0, 0, oldW, oldH);
int[] lines = new int[newW*oldH];
int[] columns = new int[newW * newH];
if (newW < oldW){
for (int k = 0; k < oldH; k++) { // trough all lines
int i = k * oldW; // index in old pix
int j = k * newW; // index in new pix
int part = newW;
int addon = 0, r=0, g=0, b=0, a=0;
for (int m=0; m<newW; m++){ ///OPTI ijm!!! need???
int total = oldW;
int R=0, G=0, B=0, A=0;
if (addon!=0){
R=r*addon; G=g*addon; B=b*addon; A=a*addon;
total-=addon;
}
while (0<total){
a = (pixels[i] >> 24) & 0xff;
r = (pixels[i] >> 16) & 0xff;
g = (pixels[i] >> 8) & 0xff;
b = pixels[i++] & 0xff;
if (total>part){
R+=r*part; G+=g*part; B+=b*part; A+=a*part;
}
else{
R+=r*total; G+=g*total; B+=b*total; A+=a*total;
addon = part - total;
///set new pixel
lines[j++]=((R/oldW)<<16)|((G/oldW)<<8)|
(B/oldW)|((A/oldW)<<24); // A??
}
total-=part;
}
}
}
}
else{ /// newW > oldW
int part = oldW;
for (int k = 0; k < oldH; k++) { // trough all lines
int i = k * oldW; // index in old pix
int j = k * newW; // index in new pix
int total= 0;
int r=0, g=0, b=0, a=0;
for (int m=0; m<newW; m++){
int R=0, G=0, B=0, A=0;
if (total>=part){
R=r*part; G=g*part; B=b*part; A=a*part;
total-=part;
}
else{
if (0!=total){
R=r*total; G=g*total; B=b*total; A=a*total;
}
a = (pixels[i] >> 24) & 0xff;
r = (pixels[i] >> 16) & 0xff;
g = (pixels[i] >> 8) & 0xff;
b = pixels[i++] & 0xff;
int addon = part - total;
R+=r*addon; G+=g*addon; B+=b*addon; A+=a*addon;
total=newW - addon;
}
///set new pixel
lines[j++]=((R/oldW)<<16)|((G/oldW)<<8)|
(B/oldW)|((A/oldW)<<24); // A??
}
}
}
/// проходим по столбцам
if (newH < oldH) {
for (int k = 0; k < newW; k++) { // trough columns
int i = k; // index in lines pix
int j = k; // index in new pix
int part = newH;
int addon = 0, r=0, g=0, b=0, a=0;
for (int m=0; m<newH; m++){
int total = oldH;
int R=0, G=0, B=0, A=0;
if (addon!=0){
R=r*addon; G=g*addon; B=b*addon; A=a;//*addon;
total-=addon;
}
while (0<total){
// a = (lines[i] >> 24) & 0xff;// may no rotate
a = lines[i] & 0xff000000;
r = (lines[i] >> 16) & 0xff;
g = (lines[i] >> 8) & 0xff;
b = lines[i] & 0xff;
i+=newW;
if (total>part){
R+=r*part; G+=g*part; B+=b*part; A+=a;//*part;
}
else{
R+=r*total; G+=g*total; B+=b*total; A+=a;//*total;
addon = part - total;
///set new pixel
if (0!=A)
columns[j]=((R/oldH)<<16)|((G/oldH)<<8)|
(B/oldH)|0xff000000; // A??
else
columns[j]=0;//((R/oldH)<<16)|((G/oldH)<<8)|(B/oldH); // A??
j+=newW;
}
total-=part;
}
}
}
}
else{
int part = oldH;
for (int k = 0; k < newW; k++) { // trough all lines
int i = k; // index in old pix
int j = k; // index in new pix
int total= 0;
int r=0, g=0, b=0, a=0;
for (int m=0; m<newH; m++){
int R=0, G=0, B=0, A=0;
if (total>=part){
R=r*part; G=g*part; B=b*part; A=a;//*part;
total-=part;
}
else{
if (0!=total){
R=r*total; G=g*total; B=b*total; A=a;//*total;
}
// a = (lines[i] >> 24) & 0xff;// may no rotate
a = lines[i] & 0xff000000;
r = (lines[i] >> 16) & 0xff;
g = (lines[i] >> 8) & 0xff;
b = lines[i] & 0xff;
i+=newW;
int addon = part - total;
R+=r*addon; G+=g*addon; B+=b*addon; A+=a;//*addon;
total=newH - addon;
}
///set new pixel
if (0!=A)
columns[j]=((R/oldH)<<16)|((G/oldH)<<8)|
(B/oldH)|0xff000000; // A??
else
columns[j]=0;//((R/oldH)<<16)|((G/oldH)<<8)|(B/oldH);
j+=newW;
}
}
}
return Image.createRGBImage(columns,newW,newH,true);
}
public void fullReset(){
String rsname="S3DEditor 0.6";
try{
RecordStore.deleteRecordStore(rsname);
notifyDestroyed();
}catch(Exception e){}
}
}

534
src/MainMenu.java Normal file
View File

@ -0,0 +1,534 @@
// Главное меню программы.
import javax.microedition.io.*;
import javax.microedition.io.file.FileConnection;
import javax.microedition.lcdui.*;
import java.io.*;
public class MainMenu extends Canvas implements CommandListener
{
Menu menu;
int m,w,h;
int sh = Statics.font.getHeight();
String title;
public MainMenu()
{
setFullScreenMode(true);
menu = new Menu(null, Statics.font);
Statics.w=w=getWidth();
Statics.h=h=getHeight();
Statics.pers=(int)(w*1.25);
menu.curColor = 0xcccccc;
menu.textColor=Statics.menuTextColor;
menu.selTextColor=Statics.menuTextColor;
}
void toMenu() {
if(Main.main.e==null) menu.setElems(new String[] { Statics.russian?"Файл":"File", Statics.russian?"Настройки":"Settings", Statics.russian?"Дополнительно":"Extra"});
else menu.setElems(new String[] {Statics.russian?"Файл":"File", Statics.russian?"Настройки":"Settings", Statics.russian?"Дополнительно":"Extra", Statics.russian?"Визуализировать":"Render"});
title = Statics.russian?"Меню":"Menu";
m = 0; }
void toFile() {
menu.setElems(new String[] { Statics.russian?"Новый":"New", Statics.russian?"Открыть":"Open", Statics.russian?"Сохранить":"Save", Statics.russian?"Справка":"Help", Statics.russian?"Инфо":"About", Statics.russian?"Выход":"Exit" });
title = Statics.russian?"Файл":"File";
m = 1; }
void toSet() {
menu.setElems(new String[] { Statics.russian?"Общие":"General", Statics.russian?"Цвета":"Color scheme", Statics.russian?"Сброс":"Full reset"});
title = Statics.russian?"Настройки":"Settings";
m = 2; }
void toColors() {
menu.setElems(new String[] { Statics.russian?"Фон редактора":"Editor field", Statics.russian?"Курсор":"Cursor", Statics.russian?"Сетка":"Grid", Statics.russian?"Фон меню":"Menu background", Statics.russian?"Текст":"Text", Statics.russian?"Эл-ты меню":"Menu items",Statics.russian?"Фон рендера":"Render background"});
title = Statics.russian?"Цвета":"Color scheme";
m = 3; }
void toDop() {
if(Main.main.e==null) menu.setElems(new String[] {Statics.russian?"Примеры":"Examples"});
else menu.setElems(new String[] {Statics.russian?"Примеры":"Examples",Statics.russian?"Сброс вида":"Reset view",Statics.russian?"Описание":"Description"});
title = Statics.russian?"Дополнительно":"Extra";
m = 4; }
void toExamples() {
menu.setElems(new String[] {Statics.russian?"Кубы":"Cubes",Statics.russian?"Домик":"Home",Statics.russian?"Танк":"Tank",Statics.russian?"Логотип":"Logo"});
title = Statics.russian?"Примеры":"Examples";
m = 5;
}
void toSettings(){
Form set=new Form(Statics.russian?"Настройки":"General Settings");
Main.main.d.setCurrent(set);
final ChoiceGroup sett=new ChoiceGroup("",List.MULTIPLE);
sett.append(Statics.russian?"Сетка":"Grid",null);
sett.append(Statics.russian?"Вспомогательные буферы":"Extra Buffers",null);
sett.append(Statics.russian?"Сенсорный ввод":"Touch Input",null);
sett.append(Statics.russian?"Крупные иконки":"Big Icons",null);
sett.append(Statics.russian?"Случайный цвет новых объектов":"Random Color of new objects",null);
sett.setSelectedFlags(new boolean[]{Statics.grid,Statics.extraBuffers,Statics.touch,Statics.bigImages,Statics.randColor});
set.append(sett);
final TextField lim=new TextField(Statics.russian?"Дальность отрисовки":"Visible distance",""+Statics.limit,10,TextField.NUMERIC);
final TextField per=new TextField(Statics.russian?"Перспектива":"Perspective",""+Statics.pers,10,TextField.NUMERIC);
set.append(lim);
set.append(per);
final ChoiceGroup tex=new ChoiceGroup(Statics.russian?"Сжатие текстур":"Texture compression",List.EXCLUSIVE);
tex.append("Png", null);
tex.append("Jpg", null);
tex.append(Statics.russian?"Без потерь(большой размер файла)":"Lossless(huge file size)", null);
tex.append("Gif(256 colors)", null);
tex.setSelectedIndex(Statics.textureSaving, true);
set.append(tex);
final ChoiceGroup fontc=new ChoiceGroup(Statics.russian?"Шрифт":"Font size",List.EXCLUSIVE);
fontc.append(Statics.russian?"Мелкий":"Small", null);
fontc.append(Statics.russian?"Средний":"Medium",null);
fontc.append(Statics.russian?"Крупный":"Large",null);
int ii=Statics.font.getSize();
if(ii==Font.SIZE_SMALL)fontc.setSelectedIndex(0, true);
else if(ii==Font.SIZE_MEDIUM)fontc.setSelectedIndex(1, true);
else fontc.setSelectedIndex(2, true);
set.append(fontc);
final ChoiceGroup lang=new ChoiceGroup(Statics.russian?"Язык":"Language",List.EXCLUSIVE);
lang.append("Русский", null);
lang.append("English",null);
lang.setSelectedIndex(Statics.russian?0:1,true);
set.append(lang);
set.addCommand(new Command("Ok",Command.OK,1));
set.setCommandListener(new CommandListener(){
public void commandAction(Command c,Displayable d){
int met;
if(fontc.getSelectedIndex()==0)met=Font.SIZE_SMALL;
else if(fontc.getSelectedIndex()==1)met=Font.SIZE_MEDIUM;
else met=Font.SIZE_LARGE;
Statics.font=Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, met);
Statics.russian=lang.getSelectedIndex()==0;
Statics.limit=Integer.parseInt(lim.getString());
Statics.pers=Integer.parseInt(per.getString());
Statics.textureSaving=tex.getSelectedIndex();
boolean[] ba=new boolean[5];
sett.getSelectedFlags(ba);
Statics.grid=ba[0];
Statics.extraBuffers=ba[1];
Statics.touch=ba[2];
Statics.bigImages=ba[3];
Statics.randColor=ba[4];
Main.main.d.setCurrent(Main.main.menu);
}
});
}
public void paint(Graphics g)
{
if(m==6){
g.drawRGB(Main.main.e.rgb, 0, w, 0, 0, w,h, false);
drawLeftSoft(g,Statics.russian?"Сохранить":"Save");
drawRightSoft(g,">");
repaint();
return;
}
g.setColor(Statics.menuBack);
g.fillRect(0, 0, w, h);
menu.paint(g, 0, h/3, w, h, 1);
//drawBorders(g);
g.setColor(Statics.textColor);
g.drawString(title, w / 2, 0, 17);
drawLeftSoft(g,Statics.russian?"Выбор":"Select");
if ((Main.main.e != null) || (m > 0))
drawRightSoft(g,Statics.russian?"Назад":"Back");
}
public void drawBorders(Graphics g) {
g.setColor(8947967);
g.fillRect(0, 0, w, sh / 2);
g.fillRect(0, h - sh + 1, w, sh / 2);
g.setColor(7632107);
g.fillRect(0, h - sh / 2 + 1, w, sh / 2);
g.fillRect(0, sh / 2, w, sh / 2);
}
private void drawLeftSoft(Graphics g,String s){
int sh=g.getFont().getHeight();
if(!Statics.touch){
g.setColor(8947967);
g.fillRoundRect(0, h - sh+1, g.getFont().stringWidth(s)+5, sh-1,10,10);
g.setColor(0);
g.drawRoundRect(0, h - sh+1, g.getFont().stringWidth(s)+5, sh-2,10,10);
g.setColor(0x555555);
g.drawString(s, 2, h - 2, 36);
g.setColor(Statics.textColor);
g.drawString(s, 3, h - 1, 36);}
else{
g.setColor(8947967);
g.fillRoundRect(0, h - 40, g.getFont().stringWidth(s)+5, 39,15,15);
g.setColor(0);
g.drawRoundRect(0, h - 40, g.getFont().stringWidth(s)+5, 38,15,15);
g.setColor(0x555555);
g.drawString(s, 2, h + sh/2 - 20, 36);
g.setColor(Statics.textColor);
g.drawString(s, 3, h +sh/2 - 19, 36);
}
}
private void drawRightSoft(Graphics g,String s){
int sh=g.getFont().getHeight();
if(!Statics.touch){
g.setColor(8947967);
g.fillRoundRect(w-g.getFont().stringWidth(s)-5, h - sh + 1, g.getFont().stringWidth(s)+5, sh-1,10,10);
g.setColor(0);
g.drawRoundRect(w-g.getFont().stringWidth(s)-5, h - sh + 1, g.getFont().stringWidth(s)+4, sh-2,10,10);
g.setColor(0x555555);
g.drawString(s, w - 4, h - 2, 40);
g.setColor(Statics.textColor);
g.drawString(s, w - 3, h - 1, 40);}
else{
g.setColor(8947967);
g.fillRoundRect(w-g.getFont().stringWidth(s)-5, h - 40, g.getFont().stringWidth(s)+5, 39,15,15);
g.setColor(0);
g.drawRoundRect(w-g.getFont().stringWidth(s)-5, h-40, g.getFont().stringWidth(s)+4, 38,15,15);
g.setColor(0x555555);
g.drawString(s, w - 4, h+sh/2- 20, 40);
g.setColor(Statics.textColor);
g.drawString(s, w - 3, h+sh/2 - 19, 40);
}
}
protected void keyPressed(int keyCode)
{
int g = getGameAction(keyCode);
if (g == 1) {
menu.up();
} else if (g == 6) {
menu.down();
} else if (g == 8) {
fire();
} else {
String strCode = null;
try {
strCode = getKeyName(keyCode).toLowerCase();
}
catch (IllegalArgumentException e) {
}
if (strCode != null)
{
if (("soft1".equals(strCode)) || ("soft 1".equals(strCode)) || ("soft_1".equals(strCode)) || ("softkey 1".equals(strCode)) || ("sk2(left)".equals(strCode)) || (strCode.startsWith("left soft"))){
fire(); return; }
if (("soft2".equals(strCode)) || ("soft 2".equals(strCode)) || ("soft_2".equals(strCode)) || ("softkey 4".equals(strCode)) || ("sk1(right)".equals(strCode)) || (strCode.startsWith("right soft"))){
back(); return;}
}
switch (keyCode)
{
case -202:
case -21:
case -6:
case 21:
case 105:
case 113:
case 57345:
fire(); break;
case -203:
case -22:
case -7:
case 22:
case 106:
case 112:
case 57346:
back(); break;
}
}
repaint(); }
public void fire() {
switch (m) {
case 0:
switch (menu.index) {
case 0:
toFile(); break;
case 1:
toSet(); break;
case 2:
toDop();break;
case 3: render();break;}
break;
case 1:
switch (menu.index) {
case 0:
newModel(); break;
case 1:
open(); break;
case 2:
save(); break;
case 3:
help(); break;
case 4:
info(); break;
case 5:
exit(); }
break;
case 2:
switch (menu.index)
{
case 0:
toSettings();break;
case 1:
toColors(); break;
case 2: Main.main.fullReset(); break;
}
break;
case 4:
switch (menu.index) {
case 0:
toExamples();break;
case 1: Main.main.resetView();break;
case 2: desc();
} break;
case 3: Main.main.setColor(menu.index+1); break;
case 5: switch(menu.index){
case 0: loadExample("/examples/cubes.s3d"); break;
case 1: loadExample("/examples/home.s3d"); break;
case 2: loadExample("/examples/tank.s3d"); break;
case 3: loadExample("/examples/logo.s3d"); break;
} break;
case 6: Main.main.toSaveRender();
}
repaint();
}
private void loadExample(String s){
Main.main.newEditor();
System.gc();
Loader l=new Loader();
if(s.endsWith(".obj"))
Main.main.e.m=l.loadObj(getClass().getResourceAsStream(s));
else Main.main.e.m=l.loadResourceAsS3D(s);
Main.main.toEditor();
}
private void render(){
m=6;
Editor e=Main.main.e;
for(int i=0;i<e.rgb.length;i++){
e.rgb[i]=Statics.background;
e.zb[i]=Integer.MAX_VALUE;
}
e.m.render(e.rgb, e.zb, e.n,1,0);
}
public void back() {
switch (m) {
case 0:
Main.main.toEditor(); break;
case 1:
case 2:
case 6:
case 4:
toMenu(); break;
case 3:
toSet(); break;
case 5:
toDop();break;
}
repaint();
}
public void newModel() {
Main.main.newEditor();
Main.main.toEditor();
}
public void open()
{
/* final TextBox tb=new TextBox("opening","E:/file.wax",1000,0);
tb.addCommand(new Command("Ok",Command.OK,1));
Main.main.d.setCurrent(tb);
tb.setCommandListener(new CommandListener() {
public void commandAction(Command c,Displayable dis){
Main.main.newEditor();
Loader l=new Loader();
try{
FileConnection fc=(FileConnection)Connector.open("file:///"+tb.getString(),Connector.READ);
if(!fc.exists()){Main.main.toEditor();l=null; }
if(tb.getString().endsWith(".wax"))
Main.main.e.m=l.openWax(fc.openInputStream());
else if(tb.getString().endsWith(".obj"))
Main.main.e.m=l.loadObj(fc.openInputStream());
l=null;
Main.main.toEditor();
}catch(Exception e){l=null; Main.main.toEditor();}
}
});*/
Main.main.toOpen();
}
public void open(String path){
Main.main.newEditor();
Loader l=new Loader();
try{
FileConnection fc=(FileConnection)Connector.open("file://"+path,Connector.READ);
if(!fc.exists()){Main.main.toEditor();l=null; }
InputStream is=fc.openInputStream();
if(path.endsWith(".wax"))
Main.main.e.m=l.openWax(is);
else if(path.endsWith(".obj"))
Main.main.e.m=l.loadObj(is);
else if(path.endsWith(".s3d"))
Main.main.e.m=l.loadS3D(is);
l=null;
is.close();
fc.close();
//Main.main.toEditor();
}catch(Exception e){l=null;}
Main.main.toEditor();
}
public void save()
{
Main.main.toSave();
}
public void save(String path){
try{
FileConnection fc=(FileConnection)Connector.open("file://"+path,Connector.READ_WRITE);
if(fc.exists())
fc.delete();
fc.create();
OutputStream os=fc.openOutputStream();
Saver.saveS3D(Main.main.e.m, MaterialEditor.mat, os);
os.close();
}catch(Exception e){}
Main.main.toEditor();
}
Form help;
List lst;
public void help()
{
help=new Form("");
lst=new List(Statics.russian?"Справка":"Help",List.IMPLICIT,new String[]{Statics.russian?"Общее":"Common",Statics.russian?"Окно редактора":"Workspace",Statics.russian?"Меню редактирования":"Edit menu",Statics.russian?"Цвет и материалы":"Colors and materials"},null);
Main.main.d.setCurrent(lst);
lst.setCommandListener(this);
help.setCommandListener(this);
Command c=new Command("Ok",Command.OK,1);
lst.addCommand(c);
help.addCommand(c);
lst.addCommand(new Command(Statics.russian?"Назад":"Back",Command.BACK,2));
}
public void info()
{
help=new Form(Statics.russian?"Инфо":"About");
if(Statics.russian)help.append("S3D Editor. Версия 0.6. Java-программа на мобильные телефоны для 3д-моделирования и творчества. В принципе, можно использовать и для 3д игр на телефон, однако это невозможно без моей java-библиотеки(движка), которую я выпущу чуть позже, а экпортировать в m3g пока нет возможности (но я работаю над этим). Все пожелания, вопросы, просьбы опять же сюда:\n e-mail: shaman_c75@mail.ru\n http://vk.com/shamanner \n http://shamansite.wen.ru \nмистер Shaman. Две тысячи тринадцатый год :)");
else help.append("S3D Editor. Version 0.6. Java-application on mobile phones for 3d-modeling and art. When java-library will be released, it will possible to develop 3d-games using this editor. I'm trying to add opportunity to import and export m3g-scenes. All questions and wishes sent there:\n e-mail: shaman_c75@mail.ru\n http://vk.com/shamanner \n http://shamansite.wen.ru \n mister Shaman, Two thousand and thirteenth :)");
help.addCommand(new Command("Ok",Command.BACK,2));
help.setCommandListener(this);
Main.main.d.setCurrent(help);
}
public void commandAction(Command com,Displayable dis){
if(com.getPriority()==2)Main.main.d.setCurrent(this);
else if(com.getPriority()==1||com==List.SELECT_COMMAND){
if(dis==help)Main.main.d.setCurrent(lst);
else{
help.deleteAll();
switch(lst.getSelectedIndex()){
case 0: help.setTitle(Statics.russian?"Общее":"Common");
if(Statics.russian)help.append("Общее описание.\n\nS3D Editor - 3D рисовалка для мобильного телефона. Есть возможность загружать модели формата *.obj, *.wax (мобильное приложение 3d studio wax), а также сохранять и загружать в собственный формат проекта *.s3d. Приложение позволяет создавать основные стереометрические примитивы и использовать полигональное моделирование, настраивать материалы для каждого полигона (текстура, прозрачность, самосвечение и т.д.), добавлять несколько точечных источников света (пока только белого цвета и фиксированной мощности) и рендерить это все в изображение.\n Также каждая модель имеет собственное название, создателя и описание, которые можно найти в главном меню в \"Дополнительно - Описание\".");
else help.append("Common description. \n\n S3D Editor - 3D paint on mobile phone. There is an opportunity to load *.obj, *.wax(mobile application 3d studio wax) and to save projects into *.s3d. Program allows to create volume figures consisting of basic stereometric primitives and manually built polygon meshes, set up material for every polygon(texture map,opacity,self illumination,etc.), add sources of lighting(now only white color and fixed capacity) and render it into image. Also every model has its name, vendor and description, that you can find in menu \"Extra - Description\"");
break;
case 1: help.setTitle(Statics.russian?"Окно редактора":"Workspace");
if(Statics.russian)help.append("Рабочее пространство представляет из себя открытое место, опциональную сетку, сверху - иконки инструментов и текущий цвет (изначально белый), снизу иконка режима. Нажав на нее(или нажав клавишу 0), откроется подменю выбора режима, которое меняется нажатиями вверх-вниз. В этом меню вы найдете режимы добавления объекта,обзора,движения,увеличения, выделения и изменения выбранных объектов.\n Поподробнее:\n Первые 4 режима уже названы - добавление, обзор, движение и масштаб. Вторые 4 режима - работа с выделением: единичный выбор (зажав звездочку или на сенсоре нажав кнопку \"Добавить\", можно выделить несколько объектов), выделение рамкой, выделение 3d-кубом и список объектов. Последние 3 режима - это сдвиг, поворот и масштабирование выделения, т.е. преобразования объектов. Ели жазать звездочку (или нажать кнопку \"Дубликат\") и нажать Ок, то измененные объекты будут копированы, сколько хочется раз.\n\n Другие возможности: \n Чтобы открыть список инструментов, нажмите левый софткей (на сенсорнике - иконка справа вверху с изображением текущего инструмента), меню редактирования - по клавише 9 (на сенсорном кнопка внизу \"Редакт\"), клавиша 7 откроет подменю типа отрисовки и обзора (или на экране нажать в левом верхнем углу), клавиша * открывает настройщик цвета, если ее зажать - откроется редактор материалов (аналогично - на экране с цветным квадратом).");
else help.append("Workspace is main window of modeling. There is optional grid, tools icon and current color(default white) upper center and mode icon on the bottom. Press on it (or press key 0) and opens mode submenu (it changes with up-down). That menu contains 11 modes of work. First 4 modes is new object,preview,move and scale view. Next 4 modes is for selection. You can pick up object (button \"add\" or pressed keystar allows picking up a few objects), select via rect and 3d-box and select via list. The last four modes is transform objects: move,rotate and scale. If pressed keystar or button \"Duplicate\", selection will be copied several times. Other buttons:\n if you press key 7 or the upper left corner of screen shading and view menu opens, key 9 or button \"Edit\" opens edition menu, tool icon in the upper right corner - list of tools,key star leads to settings of color and help key star opens material editor (for touch screen analogically with color square near the tool icon).");
break;
case 2: help.setTitle(Statics.russian?"Меню редактирования":"Edit menu");
if(Statics.russian)help.append("Меню редактирования нужно для более обширного редактирования. Сверху есть три иконки, обозначающие уровень изменения: объекты, полигоны, вершины. Т.е. если выбрать (<>) уровень полигонов и нажать назад, то в рабочем окне вы сможете выделять и взаимодействовать с полигонами и т.д. Теперь о пунктах меню:\n - Свойства. Свойства выделенного объекта (работает только если выбран один объект). Можно менять имя объекта, его видимость, узнать информацию об объекте.\n UV-координаты. Настройка текстурных координат для выбранных полигонов (на выбранном уровне полигонов разумеется). Как известно, у каждой вершины треугольника для текстурирования есть текстурные координаты, их и можно редактировать. так же клавишами * и # можно выбрать текстуру из доступных материалов для наглядного редактирования.\n Нормали. Это перпендикуляры к полигонам и вершинам, нужны в основном для освещения. Их можно обратить (перевернуть) и перерасчитать для выбранных объектов на соответствующем уровне. Не советую без необходимости перерасчитывать нормали для полигонов и объектов, т.к. чаще всего это будет неправильно и для многих треугольников придется вручную обращать нормали.\n Сглаживание. Применяется для объектов и полигонов. Включает или выключает сглаживание между полигонами наподобие групп сглаживания в 3d studio max, но здесь только две группы - сглаживание и плоское освещение.\n - Пробный материал. Назначает тестовый материал на все объекты и добавляется в список в редакторе материалов. Просто так.\n - Удалить материал. С выбранных объектов или полигонов.\n - Удалить. удаляет выбранные объекты/полигоны/вершины.\n - Отделить. Отделяет выбранные полигоны в отдельный объект.");
help.append("Edition menu is for more wide edition. Three icons define the edition level: objects, polygons and vertexes. That means if you choose (<>) polygon level in workspace you are able to select and transform only triangles in scene. Now about menu itms:\n - Properties. Properties of selected object(is available if only one object is selected) show its name, visibility,info.\n UVs - texture coordinates for selected triangles(of course, on the polygon level). Every vertex has uv coordinates according to its position on flat texture. Use * and # to change background image from available scene material.\n - Normals. It's a perpendicular for triangle. Is necessary for lighting. You can invert and recalculate it for any objects, but I don't advise to recalculate normals for objects and triangles without need because it will be incorrect and you will have to invert them manually.\n - Smooth. Turns on and off smoothing between polygons. Like smoothing groups in 3ds max but much easier.\n - Test material. Applies test material to the all objects. Just like that.\n - Delete material. Deletes material in selected polygons or objects. \n - Delete. Objects/triangles/vertexes.\n - Detach. Separates selected polygons into single object.");
break;
case 3: help.setTitle(Statics.russian?"Цвет и материалы":"Colors and materials");
if(Statics.russian)help.append("Нажав звездочку или квадрат цвета в рабочем пространстве открывает настройка цвета. Можно вручную подобрать цвет по RGB или же найти его в палитре. Соответственно, если зажать звездочку или цветной квадрат, открывается Редактор материалов. Изначально там список материалов в сцене. Если выбрать любой, можно увидеть настройки для материала. По порядку: название, непрозрачность, самосвечение, масштабирование по U и V (горизонтально и вертикально) и сдвиг по U и V(это для текстуры), цвет, текстурная карта, двухсторонняя видимость и бесцветность(т.е. независимо от текстуры или цвета материала, полигон с этим материалом будет иметь цвет, который был ему задан при создании).");
else help.append("Press * or color square in workspace and you will see setteing of color. You're able to set it manually using RGB or find color in palette. If you hold the same buttons, material editor opens. Here you may find list of materials in scene and settings for every material. In order:\n name, opacity, self illumination, scaling and offset of texture along U and V, diffuse color, texture map, double-sided visibility and colorless (independently from used color or texture, triangle draws with color which was given while creation).");
break;
}
Main.main.d.setCurrent(help);
}
}
}
public void desc(){
final Form f=new Form(Statics.russian?"Описание":"Scene descriptor");
final TextField nm=new TextField(Statics.russian?"Название:":"Name",Main.main.e.name,30,TextField.ANY),vn=new TextField(Statics.russian?"Создатель:":"Creator",Main.main.e.vendor,30,TextField.ANY),desc=new TextField(Statics.russian?"Описание:":"Description",Main.main.e.description,30,TextField.ANY);
f.append(""+Main.main.e.m.g.size()+(Statics.russian?" объектов":"objects"));
int fin=0,vin=0;
for(int i=0;i<Main.main.e.m.g.size();i++){
Group gr=(Group)Main.main.e.m.g.elementAt(i);
fin+=gr.f.size();
vin+=gr.v.size();
}
f.append(""+fin+(Statics.russian?" полигонов":"triangles"));
f.append(""+vin+(Statics.russian?" вершин":"vertexes"));
f.append(nm);
f.append(vn);
f.append(desc);
f.append((Statics.russian?"Свободно памяти":"Free heap:")+Runtime.getRuntime().freeMemory());
f.addCommand(new Command("Ok",1,1));
f.addCommand(new Command(Statics.russian?"Сборка мусора":"Collect garbage",Command.HELP,2));
Main.main.d.setCurrent(f);
f.setCommandListener(new CommandListener(){
public void commandAction(Command c,Displayable dis){
if(c.getPriority()==1){
Main.main.e.name=nm.getString();
Main.main.e.vendor=vn.getString();
Main.main.e.description=desc.getString();
Main.main.toMenu();
}
else{
System.gc();
f.delete(6);
f.append((Statics.russian?"Свободно памяти":"Free heap:")+Runtime.getRuntime().freeMemory());
}
}
});
}
public void exit() {
Main.main.destroyApp(true);
}
protected void keyReleased(int keyCode)
{
}
protected void keyRepeated(int keyCode)
{
}
protected void pointerDragged(int x, int y)
{
int t = menu.getTouchIndex(y);
if (t != 16777215)
menu.index = t;
repaint();
}
protected void pointerPressed(int xp, int yp)
{
if(yp>=h-40){
if(xp<=w/4){
fire();
}
else if(xp>=w-w/4)back();
}
int t = menu.getTouchIndex(yp);
if (t != 16777215)
menu.index = t;
repaint();
}
protected void pointerReleased(int x, int y)
{
int t = menu.getTouchIndex(y);
if (t != 16777215) {
menu.index = t;
fire();
}
repaint();
}
}

33
src/Material.java Normal file
View File

@ -0,0 +1,33 @@
// класс материала для полигона
/*
* To change this template, choose Tools | Templates and open the template in
* the editor.
*/
import javax.microedition.lcdui.Image;
/**
*
* @author Shaman
*/
public class Material {
public int diffuseColor,opacity;
public boolean doubleSided=false,useFaceColor=false;
public float self,us=1f,vs=1f,uo=0f,vo=0f; // самосвечение, масштаб текстуры по u и v, сдвиг по u и v
public int[] texture;
public int w,h;
public String desc="";
public Material(){
diffuseColor=0xffffff;
opacity=255;
self=0f;
desc="Material";
}
public void setDiffuseMap(Image im){
w=im.getWidth();
h=im.getHeight();
texture=new int[w*h];
im.getRGB(texture, 0, w, 0, 0, w, h);
}
}

602
src/MaterialEditor.java Normal file
View File

@ -0,0 +1,602 @@
// редактор матерьялов
/*
* To change this template, choose Tools | Templates and open the template in
* the editor.
*/
import java.util.Vector;
import javax.microedition.io.Connector;
import javax.microedition.lcdui.*;
/**
*
* @author Shaman
*/
public class MaterialEditor extends Canvas{
int w,h,in,md,el,sh=Statics.font.getHeight(),xs,ys,xd,yd,elnum;
float dh,hh,H;
Menu m;
int[] data;
public static Vector mat=new Vector();
Material ma;
public MaterialEditor(){
setFullScreenMode(true);
w=getWidth();
h=getHeight();
dh = 360.0f / 80;
m=new Menu(new String[]{Statics.russian?"Добавить":"Add",Statics.russian?"Применить":"Apply",Statics.russian?"Удалить":"Delete"},Statics.font);
m.textColor=Statics.textColor;
}
public void paint(Graphics g){
g.setColor(Statics.menuBack);
g.fillRect(0, 0, w, h);
if(md<=1){
g.setColor(Statics.textColor);
int is=mat.size();
String ss="";
if(Statics.russian){
String s2=Integer.toString(mat.size());
short ii=Short.parseShort(s2.substring(s2.length()-1));
if(is>=10&&is<=20)ss="ов";
else{
if(ii==1)ss="";
else if(ii>=2&&ii<=4)ss="а";
else if(ii==0||ii>=5&&ii<=9)ss="ов";
}
}
else{
if(is>1)ss="s";
}
g.setFont(Statics.font);
g.drawString(""+is+(Statics.russian?" материал":" material")+ss, w/2, 0, 17);
g.setColor(0x777777);
g.drawRect( 3,sh+3, w-6, h-sh*2-6);
int jx=5,jy=sh+5;
for(int i=0;i<is;i++){
Material mm=(Material)mat.elementAt(i);
if(mm.texture==null){
g.setColor(mm.diffuseColor);
g.fillRect(jx+1, jy+1, 49, 49);
}
else{
if(mm.w>=49) g.drawRGB(mm.texture, 0, mm.w, jx+1, jy+1, 49, mm.h>=49?49:mm.h, false);
else g.drawRGB(mm.texture, 0, mm.w, jx+25-mm.w/2, jy+25-mm.w/2, mm.w, mm.h>=49?49:mm.h, false);
}
if(in==i){g.setColor(0xaa0000);
g.drawRect(jx+1, jy+1, 48, 48);
}
else g.setColor(0x777777);
g.drawRect(jx, jy, 50, 50);
jx+=60;
if(jx+50>w-3){jy+=60;jx=5;}
}
if(md==1){
m.paint(g, 0, h-m.f.getHeight()*3, m.f.stringWidth(Statics.russian?"Применить":"Delete"), 100, 1);
}
else if(md==0){if(is==0)drawLeftSoft(g,Statics.russian?"Добавить":"Add");
else drawLeftSoft(g,Statics.russian?"Опции":"Options");}
drawRightSoft(g,Statics.russian?"Назад":"Back");
}
else if(md==2||md==3){
g.setColor(ma.diffuseColor);
g.fillRect(w/2-65, 18+sh*5, 60, 60);
if(ma.texture!=null){
if(ma.w>=60) g.drawRGB(ma.texture, 0, ma.w, w/2+5, 18+sh*5, 60, ma.h>=60?60:ma.h, false);
else g.drawRGB(ma.texture, 0, ma.w, w/2+35-ma.w/2, 48+sh*5-30, ma.w, ma.h>=60?60:ma.h, false);}
else{
g.setColor(0xffffff);
g.fillRect(w/2+5, 18+sh*5, 60, 60);
g.setColor(0xff0000);
g.drawLine(w/2+5, 18+sh*5, w/2+65, 78+sh*5);
g.drawLine(w/2+5, 78+sh*5, w/2+65, 18+sh*5);
}
g.setColor(0xbbbbbb);
g.fillRect(3, 3, w-6, sh);
g.fillRect(w/2-Statics.font.stringWidth("999")/2, 6+sh, Statics.font.stringWidth("999"), sh);
g.fillRect(w/2-Statics.font.stringWidth("999")/2, 9+sh*2, Statics.font.stringWidth("999"), sh);
g.fillRect(w/2-Statics.font.stringWidth("9999"), 12+sh*3, Statics.font.stringWidth("9999"), sh);
g.fillRect(w/2+Statics.font.stringWidth("Vscl "), 12+sh*3, Statics.font.stringWidth("9999"), sh);
g.fillRect(w/2-Statics.font.stringWidth("9999"), 15+sh*4, Statics.font.stringWidth("9999"), sh);
g.fillRect(w/2+Statics.font.stringWidth("Voff "), 15+sh*4, Statics.font.stringWidth("9999"), sh);
g.fillRect(w/2-Statics.font.stringWidth(Statics.russian?" двухсторонний":" double-sided")/2-20, 18+sh*5+63, 20, 20);
g.fillRect(w/2-Statics.font.stringWidth(Statics.russian?" бесцветный":" colorless")/2-20, 18+sh*6+63, 20, 20);
g.drawRect(w/2-65, 18+sh*5, 60, 60);
g.drawRect(w/2+5, 18+sh*5, 60, 60);
if(ma.doubleSided){
g.setColor(0x555555);
g.fillRect(w/2-Statics.font.stringWidth(Statics.russian?" двухсторонний":" double-sided")/2-16, 18+sh*5+67, 12, 12);
}
if(ma.useFaceColor){
g.setColor(0x555555);
g.fillRect(w/2-Statics.font.stringWidth(Statics.russian?" бесцветный":" colorless")/2-16, 18+sh*6+67, 12, 12);
}
g.setColor(Statics.textColor);
g.setFont(Statics.font);
g.drawString(ma.desc, w/2, 3, 17);
g.drawString((Statics.russian?"непрозрачность ":"opacity ")+ma.opacity, w/2+Statics.font.stringWidth("999")/2+1, 6+sh, Graphics.RIGHT|Graphics.TOP);
g.drawString("self "+(new Float(ma.self*100).intValue()), w/2+Statics.font.stringWidth("999")/2, 9+sh*2, Graphics.RIGHT|Graphics.TOP);
g.drawString("Uscl "+String.valueOf(ma.us).substring(0, String.valueOf(ma.us).indexOf('.')+2), w/2, 12+sh*3, Graphics.RIGHT|Graphics.TOP);
g.drawString("Vscl "+String.valueOf(ma.vs).substring(0, String.valueOf(ma.vs).indexOf('.')+2), w/2, 12+sh*3, Graphics.LEFT|Graphics.TOP);
g.drawString("Uoff "+String.valueOf(ma.uo).substring(0, String.valueOf(ma.uo).indexOf('.')+2), w/2, 15+sh*4, Graphics.RIGHT|Graphics.TOP);
g.drawString("Voff "+String.valueOf(ma.vo).substring(0, String.valueOf(ma.vo).indexOf('.')+2), w/2, 15+sh*4, Graphics.LEFT|Graphics.TOP);
g.drawString(Statics.russian?" двухсторонний":" double-sided", w/2, 18+sh*5+63, 17);
g.drawString(Statics.russian?" бесцветный":" colorless", w/2, 21+sh*6+63, 17);
int xe=0,ye=0,xxe=0,yye=sh;
//String des=null;
switch(el){
case 0: ye=3; xe=3; xxe=w-6;/*des="material name";*/ break;
case 1: ye=6+sh; xe=w/2-Statics.font.stringWidth("999")/2; xxe=Statics.font.stringWidth("999");break;
case 2: ye=9+sh*2; xe=w/2-Statics.font.stringWidth("999")/2; xxe=Statics.font.stringWidth("999");break;
case 3: ye=12+sh*3; xe=w/2-Statics.font.stringWidth("9999"); xxe=Statics.font.stringWidth("9999");break;
case 4: ye=12+sh*3; xe=w/2+Statics.font.stringWidth("Vscl "); xxe=Statics.font.stringWidth("9999");break;
case 5: ye=15+sh*4; xe=w/2-Statics.font.stringWidth("9999"); xxe=Statics.font.stringWidth("9999");break;
case 6: ye=15+sh*4; xe=w/2+Statics.font.stringWidth("Voff "); xxe=Statics.font.stringWidth("9999");break;
case 7: ye=18+sh*5; xe=w/2-65; xxe=60; yye=60;break;
case 8: ye=18+sh*5; xe=w/2+5; xxe=60; yye=60;break;
case 9: xe=w/2-Statics.font.stringWidth(Statics.russian?" двухсторонний":" double-sided")/2-20; ye=18+sh*5+63; xxe=20; yye=20; break;
case 10: xe=w/2-Statics.font.stringWidth(Statics.russian?" бесцветный":" colorless")/2-20; ye=18+sh*6+63; xxe=20; yye=20; break;
}
g.setColor(0xcccc00);
g.drawRect(xe, ye, xxe, yye);
g.drawRect(xe+1, ye+1, xxe-2, yye-2);
drawRightSoft(g,Statics.russian?"Назад":"Back");
if(md==3){
g.setColor(0x888888);
g.fillRect(w/2-45, sh*2, 90, 119);
g.setColor(0xbbbb22);
g.drawRect(w/2-45, sh*2, 90, 119);
hh = 0;
for (int i = 0; i < 80; i++) {
int[] dt = Color.HSVtoRGB((int) hh, 255, 255);
hh += dh;
if(Math.abs(Math.floor(H)-Math.floor(hh))<=10)
g.setColor(255-dt[0],255-dt[1],255-dt[2]);
else
g.setColor(dt[0], dt[1], dt[2]);
g.drawLine(w/2-40 + i, sh*2+6, w/2-40 + i, sh*2+24);
}
g.drawRGB(data, 0, 80, w/2-40, sh*2+39, 80, 80, false);
g.setColor(0x222222);
g.drawArc(w/2-50+xd, sh*2+29+yd, 20, 20, 0, 360);
}
}
else if(md>=4){
if(ma.texture!=null){
g.drawRGB(ma.texture, 0, ma.w, w/2-ma.w/2, h/2-ma.h/2, ma.w, ma.h, true);
g.setColor(0);
g.drawRect(w, w, w, h);
}
else{
g.setFont(Statics.font);
g.setColor(0xffffff);
g.fillRect(w/2-50, h/2-50, 100, 100);
g.setColor(0xff0000);
g.drawLine(w/2-50, h/2-50, w/2+50, h/2+50);
g.drawLine(w/2+50, h/2-50, w/2-50, h/2+50);
g.setColor(0);
g.drawRect(w/2-51, h/2-51, 102, 102);
g.drawString("no texture map", w/2, h/2, 17);
}
drawLeftSoft(g,Statics.russian?"Назад":"Back");
if(ma.texture==null)drawRightSoft(g,Statics.russian?"Добавить":"Add"); else drawRightSoft(g,Statics.russian?"Опции":"Options");
if(md==5){
g.setColor(Statics.menuBack);
g.fillRect(w-Statics.font.stringWidth(Statics.russian?"Удалить":"Delete"), h-sh*2, Statics.font.stringWidth(Statics.russian?"Удалить":"Delete"), sh*2);
g.setColor(0);
g.drawRect(w-Statics.font.stringWidth(Statics.russian?"Удалить":"Delete"), h-sh*2, Statics.font.stringWidth(Statics.russian?"Удалить":"Delete"), sh*2);
g.setColor(0xaaaa00);
g.fillRect(w-Statics.font.stringWidth(Statics.russian?"Удалить":"Delete"), h-sh*(2-elnum), Statics.font.stringWidth(Statics.russian?"Удалить":"Delete"), sh);
g.setColor(Statics.menuTextColor);
g.drawString(Statics.russian?"Сменить":"Change", w, h-sh, Graphics.RIGHT|Graphics.BOTTOM);
g.drawString(Statics.russian?"Удалить":"Delete", w, h, Graphics.RIGHT|Graphics.BOTTOM);
}
}
repaint();
}
private void updateData(float H){
//palitra
if(data==null)data=new int[80*80];
float ds=255f/80f;
float dv=255f/80f;
float v = 255;
float s;
for (int i = 0; i < 80; i++) {
s = 255;
for (int i2 = 0; i2 < 80; i2++) {
int[] dt = Color.HSVtoRGB((int) H, (int) s,(int) v);
data[(i * 80) + i2] = dt[0] << 16 | dt[1] << 8 | dt[2];
s -= ds;
}
v -= dv;
}
}
private void drawLeftSoft(Graphics g,String s){
if(!Statics.touch){
g.setColor(8947967);
g.fillRoundRect(0, h - sh+1, g.getFont().stringWidth(s)+5, sh-1,10,10);
g.setColor(0);
g.drawRoundRect(0, h - sh+1, g.getFont().stringWidth(s)+5, sh-2,10,10);
g.setColor(0x555555);
g.drawString(s, 2, h - 2, 36);
g.setColor(Statics.textColor);
g.drawString(s, 3, h - 1, 36);}
else{
g.setColor(8947967);
g.fillRoundRect(0, h - 40, g.getFont().stringWidth(s)+5, 39,15,15);
g.setColor(0);
g.drawRoundRect(0, h - 40, g.getFont().stringWidth(s)+5, 38,15,15);
g.setColor(0x555555);
g.drawString(s, 2, h + sh/2 - 20, 36);
g.setColor(Statics.textColor);
g.drawString(s, 3, h +sh/2 - 19, 36);
}
}
private void drawRightSoft(Graphics g,String s){
if(!Statics.touch){
g.setColor(8947967);
g.fillRoundRect(w-g.getFont().stringWidth(s)-5, h - sh + 1, g.getFont().stringWidth(s)+5, sh-1,10,10);
g.setColor(0);
g.drawRoundRect(w-g.getFont().stringWidth(s)-5, h - sh + 1, g.getFont().stringWidth(s)+4, sh-2,10,10);
g.setColor(0x555555);
g.drawString(s, w - 4, h - 2, 40);
g.setColor(Statics.textColor);
g.drawString(s, w - 3, h - 1, 40);}
else{
g.setColor(8947967);
g.fillRoundRect(w-g.getFont().stringWidth(s)-5, h - 40, g.getFont().stringWidth(s)+5, 39,15,15);
g.setColor(0);
g.drawRoundRect(w-g.getFont().stringWidth(s)-5, h-40, g.getFont().stringWidth(s)+4, 38,15,15);
g.setColor(0x555555);
g.drawString(s, w - 4, h+sh/2- 20, 40);
g.setColor(Statics.textColor);
g.drawString(s, w - 3, h+sh/2 - 19, 40);
}
}
protected void keyPressed(int key){
String strCode = "null";
try {
strCode = getKeyName(key).toLowerCase();
}
catch (IllegalArgumentException e) {
}
// if (strCode != null)
// {
if (((("soft1".equals(strCode)) || ("soft 1".equals(strCode)) || ("soft_1".equals(strCode)) || ("softkey 1".equals(strCode)) || ("sk2(left)".equals(strCode)) || (strCode.startsWith("left soft")))))
{ if( mat.isEmpty()){
mat.addElement(new Material()); in=0;} else if(md==0)md=1; else if(md==1)fire(); else if(md==3)md=2; else if(md==4)md=2; else if(md==5)md=4; return;
}
else if (("soft2".equals(strCode)) || ("soft 2".equals(strCode)) || ("soft_2".equals(strCode)) || ("softkey 4".equals(strCode)) || ("sk1(right)".equals(strCode)) || (strCode.startsWith("right soft"))){
if(md==1)md=0;
else if(md==0)Main.main.toEditor();
else if(md==2)md=0;
else if(md==3){
md=2; ma.diffuseColor=data[yd*80+xd]; data=null; }
else if(md==4){
if(ma.texture==null)setNewMap();
else md=5;
}
else if(md==5){
if(elnum==0)setNewMap();
else if(elnum==1) deleteMap();
}
return; }
else switch (key)
{
case -202:
case -21:
case -6:
case 21:
case 105:
case 113:
case 57345:
if(mat.isEmpty()){
mat.addElement(new Material()); in=0;} else if(md==0)md=1; else if(md==1)fire(); else if(md==3)md=2; else if(md==4)md=2; else if(md==5)md=4;
break;
case -203:
case -22:
case -7:
case 22:
case 106:
case 112:
case 57346:
if(md==1)md=0;
else if(md==0)Main.main.toEditor();
else if(md==2)md=0;
else if(md==3){
md=2; ma.diffuseColor=data[yd*80+xd]; data=null;}
else if(md==4){
if(ma.texture==null)setNewMap();
else md=5;
}
else if(md==5){
if(elnum==0)setNewMap();
else if(elnum==1) deleteMap();
}
break;
case 53:// mat.addElement(new Material());break;
}
int gameact=getGameAction(key);
switch(gameact){
case LEFT: if(md==0){if(--in<0) in=mat.size()-1;} else if(md==2&&(key<49||key>57)&&el>0){
el--;
}
else if(md==3){
if(xd>1)xd-=2;
}
break;
case RIGHT: if(md==0){if(++in>=mat.size())in=0;} else if(md==2&&(key<49||key>57)&&el<10)el++; else if(md==3){if(xd<78)xd+=2; } break;
case UP: if(md==0){int num=(w-8+10)/60;
in-=num;
if(in<0)in=mat.size()-1;}else if(md==1)m.up();
else if(md==2&&el>0){
if(el<4||el==9||el==10)el--;
else if(el==4||el==5||el==7)el-=2;
else el-=3;
}
else if(md==3){if(yd>1)yd-=2;}
else if(md==5){
elnum--;
if(elnum<0)elnum=1;
}
break;
case DOWN: if(md==0){int numm=(w-8+10)/60;
in+=numm;
if(in>=mat.size())in=0;}else if(md==1) m.down();
else if(md==2&&el<10){
if(el==3||el==5)el+=2;
else el++;
}
else if(md==3){
if(yd<78)yd+=2;
}else if(md==5){
elnum++;
if(elnum>1)elnum=0;
}
break;
case FIRE: if(md==1) fire(); else if(md==0&&!mat.isEmpty()){md=2; ma=(Material)mat.elementAt(in); } else if(md==2){
if(el==0)editMatName();
else if(el==7){md=3;
float[] dt=Color.RGBtoHSV(ma.diffuseColor>>16&0xff, ma.diffuseColor>>8 &0xff,ma.diffuseColor&0xff);
H=dt[0];
xd=(int)(dt[1]*80/255);
yd=(int)(dt[2]*80/255);
updateData(H);
}
else if(el==8)md=4;
else if(el==9)ma.doubleSided=!ma.doubleSided;
else if(el==10)ma.useFaceColor=!ma.useFaceColor;
}
else if(md==5){
if(elnum==0)setNewMap();
else deleteMap();
}
break;
}
if(md==2&&(key==52||key==54)){
int tmp;
if(key==52)tmp=-1; else tmp=1;
switch(el){
case 1: if(ma.opacity<=255&&ma.opacity>=0)ma.opacity+=5*tmp; if(ma.opacity<0)ma.opacity=0;if(ma.opacity>255)ma.opacity=255;break;
case 2: if(ma.self>=0&&ma.self<=1)ma.self+=0.05f*tmp;if(ma.self<0)ma.self=0;if(ma.self>1)ma.self=1;break;
case 3: ma.us+=tmp*0.05f;break;
case 4: ma.vs+=tmp*0.05f;break;
case 5: ma.uo+=tmp*0.1f;break;
case 6: ma.vo+=tmp*0.1f;break;
}
}
if(md==3&&key==49){if((H-=5)<0)H=360; updateData(H); }
if(md==3&&key==51){if((H+=5)>=360)H=0; updateData(H); }
}
private void setNewMap(){
Main.main.toOpenMap();
}
private void deleteMap(){
ma.texture=null;
md=4;
}
public void setMap(Image img){
ma.setDiffuseMap(img);
}
protected void keyRepeated(int key){
if(md==3){
int ga=getGameAction(key);
if(ga==LEFT&&xd>4)xd-=5;
if(ga==RIGHT&&xd<75)xd+=5;
if(ga==UP&&yd>4)yd-=5;
if(ga==DOWN&&yd<75)yd+=5;
if(key==49){if((H-=5)<0)H=360; updateData(H); }
if(key==51){if((H+=5)>=360)H=0; updateData(H); }
}
else if(md==2&&(key==52||key==54)){
int tmp;
if(key==52)tmp=-1; else tmp=1;
switch(el){
case 1: if(ma.opacity<=255&&ma.opacity>=0)ma.opacity+=5*tmp; if(ma.opacity<0)ma.opacity=0;if(ma.opacity>255)ma.opacity=255;break;
case 2: if(ma.self>=0&&ma.self<=1)ma.self+=0.05f*tmp;if(ma.self<0)ma.self=0;if(ma.self>1)ma.self=1;break;
case 3: ma.us+=tmp*0.05f;break;
case 4: ma.vs+=tmp*0.05f;break;
case 5: ma.uo+=tmp*0.1f;break;
case 6: ma.vo+=tmp*0.1f;break;
}
}
}
public void fire(){
switch(m.index){
case 0: mat.addElement(new Material());break;
case 1: if(!mat.isEmpty()){
if(Edit.mo==0&&Editor.sel!=null)
for (int i=0;i<Editor.sel.size();i++){
if(Editor.sel.elementAt(i) instanceof Group)
((Group)Editor.sel.elementAt(i)).setMaterial((Material)mat.elementAt(in));
}
else if(Edit.mo==1&&Editor.sel2!=null){
for(int i=0;i<Editor.sel2.size();i++)
((Triangle)Editor.sel2.elementAt(i)).material=(Material)mat.elementAt(in);
}
Main.main.toEditor();
}break;
case 2: if(!mat.isEmpty()){mat.removeElementAt(in); if(--in<0) in=mat.size()-1;} break;
}
md=0;
}
protected void pointerPressed(int xp,int yp){
if(md==0){
if(yp>=h-40&&xp<=w/4){
if(mat.isEmpty()){
mat.addElement(new Material()); in=0;} else md=1;
}
else if(yp>=h-40&&xp>=w-w/4){
Main.main.toEditor();
}
else{
int wiw=(w+5)/60;
int iis=(xp-5)/60+(yp-sh-5)/60*wiw;
if(iis>=0&&iis<mat.size()){
if(iis!=in)in=iis;
else{md=2; ma=(Material)mat.elementAt(in); }
}
}
}
else if(md==1){
if(xp<=Statics.font.stringWidth(Statics.russian?"Применить":"Delete")){
int ind=2-((h-yp)/m.sh);
if(ind>=0&&ind<3)
if(m.index==ind)fire(); else m.index=ind;}
if(yp>=h-40&&xp>=w-w/4){
md=0;
}
}
else if(md==2){
if(yp>=h-40&&xp>=w-w/4){
md=0;
}
else if(yp>=3 && xp>=3 && xp<=w-6 && yp<=3+sh){
el=0;
editMatName();
}
else if(yp>=6+sh && xp>=w/2-Statics.font.stringWidth("999")/2 && xp<=w/2+Statics.font.stringWidth("999")/2 && yp<=sh*2+6){
el=1;
}
else if(yp>=9+sh*2 && xp>=w/2-Statics.font.stringWidth("999")/2 && xp<=w/2+Statics.font.stringWidth("999")/2 && yp<=9+sh*3){
el=2;
}
else if(yp>=12+sh*3 && xp>=w/2-Statics.font.stringWidth("9999") && xp<=w/2 && yp<=12+sh*4){
el=3;
}
else if(yp>=12+sh*3 && xp>=w/2+Statics.font.stringWidth("Vscl ") && xp<=w/2+Statics.font.stringWidth("Vscl 9999") && yp<=12+sh*4){
el=4;
}
else if(yp>=15+sh*4 && xp>=w/2-Statics.font.stringWidth("9999") && xp<=w/2 && yp<=15+sh*5){
el=5;
}
else if(yp>=15+sh*4 && xp>=w/2+Statics.font.stringWidth("Voff ") && xp<=w/2+Statics.font.stringWidth("Voff 9999") && yp<=15+sh*5){
el=6;
}
else if(yp>=18+sh*5 && xp>=w/2-65 && xp<=w/2-5 && yp<=78+sh*5){
el=7;
md=3;
float[] dt=Color.RGBtoHSV(ma.diffuseColor>>16&0xff, ma.diffuseColor>>8 &0xff,ma.diffuseColor&0xff);
H=dt[0];
xd=(int)(dt[1]*80/255);
yd=(int)(dt[2]*80/255);
updateData(H);
}
else if(yp>=18+sh*5 && xp>=w/2+5 && xp<=w/2+65 && yp<=78+sh*5){
el=8;
md=4;
}
else if(yp>=18+sh*5+63 && xp>=w/2-Statics.font.stringWidth(Statics.russian?" двухсторонний":" double-sided")/2-20 && xp<=w/2-Statics.font.stringWidth(Statics.russian?" двухсторонний":" double-sided")/2 && yp<=18+sh*5+83){
el=9;
ma.doubleSided=!ma.doubleSided;
}
else if(yp>=18+sh*6+63 && xp>=w/2-Statics.font.stringWidth(Statics.russian?" бесцветный":" colorless")/2-20 && xp<=w/2-Statics.font.stringWidth(Statics.russian?" бесцветный":" colorless")/2 && yp<=18+sh*6+83){
el=10;
ma.useFaceColor=!ma.useFaceColor;
}
xs=xp;
ys=yp;
}
else if(md==3){
if(yp>=h-40&&xp>=w-w/4){
md=2;
ma.diffuseColor=data[yd*80+xd];
data=null;}
else if(xp>=w/2-40&&xp<w/2+40){
if(yp>=sh*2+6&&yp<=sh*2+24){H=(xp-w/2+40)*360/80; if(H>=360)H=0; if(H<0)H=360; updateData(H); }
else if(yp>=sh*2+39&&yp<sh*2+119){
xd=(xp-w/2+40);
yd=yp-sh*2-39;
}
}
}
else if(md==4){
if(yp>=h-40&&xp>=w-w/4){
if(ma.texture==null)setNewMap(); else md=5;
}
else if(yp>=h-40&&xp<=w/4){
if(md==4)md=2;
}
}
else if(md==5){
if(xp>=w-Statics.font.stringWidth(Statics.russian?"Удалить":"Delete")){
if(yp>=h-sh){
elnum=1;
deleteMap();
}
else if(yp>=h-sh*2){
elnum=0;
setNewMap();
}
}
else if(yp>=h-40&&xp<=w/4){
md=4;
}
}
}
protected void pointerDragged(int xp, int yp){
if(md==2){
switch(el){
case 1: if(ma.opacity<=255&&ma.opacity>=0)ma.opacity+=xp-xs; if(ma.opacity<0)ma.opacity=0;if(ma.opacity>255)ma.opacity=255;break;
case 2: if(ma.self>=0&&ma.self<=1)ma.self+=((float)(xp-xs))/100f;if(ma.self<0)ma.self=0;if(ma.self>1)ma.self=1;break;
case 3: ma.us+=(xp-xs)*0.05f;break;
case 4: ma.vs+=(xp-xs)*0.05f;break;
case 5: ma.uo+=(xp-xs)*0.1f;break;
case 6: ma.vo+=(xp-xs)*0.1f;break;
}
xs=xp;
ys=yp;
}
else if(md==3){
if(xp>=w/2-40&&xp<w/2+40){
if(yp>=sh*2+6&&yp<=sh*2+24){H=(xp-w/2+40)*360/80;if(H>=360)H=0; if(H<0)H=360; updateData(H); }
else if(yp>=sh*2+39&&yp<sh*2+119){
xd=(xp-w/2+40);
yd=yp-sh*2-39;
}
}
}
}
private void editMatName(){
final TextBox tb=new TextBox(Statics.russian?"Имя материала":"Material name",ma.desc,1000,0);
tb.addCommand(new Command("Ok",Command.OK,1));
tb.setCommandListener(new CommandListener(){
public void commandAction(Command com, Displayable dis){
ma.desc=tb.getString();
Main.main.d.setCurrent(Main.main.me);
}
});
Main.main.d.setCurrent(tb);
}
}

209
src/Matrix3D.java Normal file
View File

@ -0,0 +1,209 @@
// класс матрицы для трансформаций вершин
public class Matrix3D
{
public float xx;
public float xy;
public float xz;
public float xo;
public float yx;
public float yy;
public float yz;
public float yo;
public float zx;
public float zy;
public float zz;
public float zo;
public Matrix3D()
{
xx = 1F;
yy = 1F;
zz = 1F;
}
public void scale(float f)
{
xx *= f;
xy *= f;
xz *= f;
xo *= f;
yx *= f;
yy *= f;
yz *= f;
yo *= f;
zx *= f;
zy *= f;
zz *= f;
zo *= f;
}
public void scale(float xf, float yf, float zf)
{
xx *= xf;
xy *= xf;
xz *= xf;
xo *= xf;
yx *= yf;
yy *= yf;
yz *= yf;
yo *= yf;
zx *= zf;
zy *= zf;
zz *= zf;
zo *= zf;
}
public void translate(float x, float y, float z)
{
xo += x;
yo += y;
zo += z;
}
public void yrot(double theta)
{
theta *= 0.017453292519943295D;
double ct = Math.cos(theta);
double st = Math.sin(theta);
float Nxx = (float)(xx * ct + zx * st);
float Nxy = (float)(xy * ct + zy * st);
float Nxz = (float)(xz * ct + zz * st);
float Nxo = (float)(xo * ct + zo * st);
float Nzx = (float)(zx * ct - xx * st);
float Nzy = (float)(zy * ct - xy * st);
float Nzz = (float)(zz * ct - xz * st);
float Nzo = (float)(zo * ct - xo * st);
xo = Nxo;
xx = Nxx;
xy = Nxy;
xz = Nxz;
zo = Nzo;
zx = Nzx;
zy = Nzy;
zz = Nzz;
}
public void xrot(double theta)
{
theta *= 0.017453292519943295D;
double ct = Math.cos(theta);
double st = Math.sin(theta);
float Nyx = (float)(yx * ct + zx * st);
float Nyy = (float)(yy * ct + zy * st);
float Nyz = (float)(yz * ct + zz * st);
float Nyo = (float)(yo * ct + zo * st);
float Nzx = (float)(zx * ct - yx * st);
float Nzy = (float)(zy * ct - yy * st);
float Nzz = (float)(zz * ct - yz * st);
float Nzo = (float)(zo * ct - yo * st);
yo = Nyo;
yx = Nyx;
yy = Nyy;
yz = Nyz;
zo = Nzo;
zx = Nzx;
zy = Nzy;
zz = Nzz;
}
public void zrot(double theta)
{
theta *= 0.017453292519943295D;
double ct = Math.cos(theta);
double st = Math.sin(theta);
float Nyx = (float)(yx * ct + xx * st);
float Nyy = (float)(yy * ct + xy * st);
float Nyz = (float)(yz * ct + xz * st);
float Nyo = (float)(yo * ct + xo * st);
float Nxx = (float)(xx * ct - yx * st);
float Nxy = (float)(xy * ct - yy * st);
float Nxz = (float)(xz * ct - yz * st);
float Nxo = (float)(xo * ct - yo * st);
yo = Nyo;
yx = Nyx;
yy = Nyy;
yz = Nyz;
xo = Nxo;
xx = Nxx;
xy = Nxy;
xz = Nxz;
}
public void mult(Matrix3D rhs)
{
float lxx = xx * rhs.xx + yx * rhs.xy + zx * rhs.xz;
float lxy = xy * rhs.xx + yy * rhs.xy + zy * rhs.xz;
float lxz = xz * rhs.xx + yz * rhs.xy + zz * rhs.xz;
float lxo = xo * rhs.xx + yo * rhs.xy + zo * rhs.xz + rhs.xo;
float lyx = xx * rhs.yx + yx * rhs.yy + zx * rhs.yz;
float lyy = xy * rhs.yx + yy * rhs.yy + zy * rhs.yz;
float lyz = xz * rhs.yx + yz * rhs.yy + zz * rhs.yz;
float lyo = xo * rhs.yx + yo * rhs.yy + zo * rhs.yz + rhs.yo;
float lzx = xx * rhs.zx + yx * rhs.zy + zx * rhs.zz;
float lzy = xy * rhs.zx + yy * rhs.zy + zy * rhs.zz;
float lzz = xz * rhs.zx + yz * rhs.zy + zz * rhs.zz;
float lzo = xo * rhs.zx + yo * rhs.zy + zo * rhs.zz + rhs.zo;
xx = lxx;
xy = lxy;
xz = lxz;
xo = lxo;
yx = lyx;
yy = lyy;
yz = lyz;
yo = lyo;
zx = lzx;
zy = lzy;
zz = lzz;
zo = lzo;
}
public void unit()
{
xo = 0F;
xx = 1F;
xy = 0F;
xz = 0F;
yo = 0F;
yx = 0F;
yy = 1F;
yz = 0F;
zo = 0F;
zx = 0F;
zy = 0F;
zz = 1F;
}
public void transform(float[] v, int[] tv, int nvert)
{
float lxx = xx; float lxy = xy; float lxz = xz; float lxo = xo;
float lyx = yx; float lyy = yy; float lyz = yz; float lyo = yo;
float lzx = zx; float lzy = zy; float lzz = zz; float lzo = zo;
for (int i = nvert * 3; (i -= 3) >= 0; ) {
float x = v[i];
float y = v[(i + 1)];
float z = v[(i + 2)];
tv[i] = (int)(x * lxx + y * lxy + z * lxz + lxo);
tv[(i + 1)] = (int)(x * lyx + y * lyy + z * lyz + lyo);
tv[(i + 2)] = (int)(x * lzx + y * lzy + z * lzz + lzo);
}
}
public String toString() {
return "[" + xo + "," + xx + "," + xy + "," + xz + ";" + yo + "," + yx + "," + yy + "," + yz + ";" + zo + "," + zx + "," + zy + "," + zz + "]";
}
}

112
src/Menu.java Normal file
View File

@ -0,0 +1,112 @@
// графическое меню, по сути универсальное, но не красивое :)
import java.util.Enumeration;
import java.util.Vector;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
public class Menu
{
public int textColor = 0x99;
public int curColor = 0xffff00;
public int selTextColor = 0x4444ff;
public int index;
public int sh;
public int by;
public int yy,hy;
public String[] e;
Font f;
public short[] ave;
public Menu(String[] s, Font font)
{
e = s;
sh = font.getHeight();
f = font; }
public void paint(Graphics g, int px, int py, int w, int h, int align) {
yy = py;
hy=h;
g.setFont(f);
g.setColor(curColor);
int y = py + sh * index + by;
//if ((y > h + py - sh))
//by -= sh;
//if(y > py+sh)
//by -= sh;
g.fillRect(px, y, w, sh);
for (int i = 0; i < e.length; ++i) {
int z = i * sh + py + by;
if(z>=py+h)continue;
if(i==index){g.setColor(selTextColor);
}
else g.setColor(textColor);
if (align == 0)
g.drawString(e[i], px, z, 20);
else if (align == 1)
g.drawString(e[i], w / 2 + px, z, 17);
else
g.drawString(e[i], px + w, z, 24);
}
}
public void up() {
index -= 1;
if (index < 0){
index = (e.length - 1);
if(by+yy+sh*index>yy+hy-sh)by=-sh*index+hy-sh;
}
if(ave!=null)
for(int i=0;i<ave.length;i++)if(index==ave[i])up();
if(by+yy+sh*index<yy)by+=sh;
//if(by+sh*index>hy)by=-sh*index;
}
public void down() {
index += 1;
if (index >= e.length){
index = 0;
if(by+yy+sh*index<yy)by=0;
}
if(ave!=null)
for(int i=0;i<ave.length;i++)if(index==ave[i])down();
//if(by+sh*index<yy)by=sh*index;
if(by+yy+sh*index>yy+hy-sh)by-=sh;
}
public void move(int yp){
if(yp>0&&by<=0)by+=yp;
if(yp<0&&by+yy+e.length*sh>=yy+hy) by+=yp;
}
public int getTouchIndex(int y) {
int touch = (y - yy - by) / sh;
if ((touch < e.length) && (touch >= 0))
return touch;
return 16777215; }
public int getSize(){
return e.length;
}
public String getSelestedName() {
return e[index]; }
public void setElems(Enumeration en,boolean bl){
Vector v=new Vector();
if(bl)v.addElement(". .");
while(en.hasMoreElements())
v.addElement(en.nextElement().toString());
e=new String[v.size()];
v.copyInto(e);
by=0;
}
public void setElems(String[] s) {
e = s;
index = 0; }
public void setElem(int i, String s) {
if ((i >= 0) && (i < e.length))
e[i] = s;
}
}

331
src/Model.java Normal file
View File

@ -0,0 +1,331 @@
// класс содержащий модель - массив групп и источников света
import java.util.Vector;
import javax.microedition.lcdui.Graphics;
public class Model
{
Vector g;
Vector l; // освещение
public Model()
{
g = new Vector();
l=new Vector();
}
public void draw(Graphics gr, Matrix3D m) {
if(l!=null&&!l.isEmpty()){for(int i=0;i<l.size();i++){if(l.elementAt(i)!=null)((Light)l.elementAt(i)).setMatrix(m);}}
if (g.isEmpty()) return;
/* for (int i = 0; i < v.size(); i++) {
Vertex vx = (Vertex)v.elementAt(i);
vx.setMatrix(m);
}*/
for(int i=0;i<g.size();i++){
((Group)g.elementAt(i)).draw(gr, m,l);}
}
public void render(int[] r,int[] z,Matrix3D m,int shad,int view){
if(l!=null&&!l.isEmpty()){for(int i=0;i<l.size();i++){if(l.elementAt(i)!=null)((Light)l.elementAt(i)).setMatrix(m);}}
if (g.isEmpty()) return;
// if(z==null){
/* for (int i = 0; i < v.size(); i++) {
Vertex vx = (Vertex)v.elementAt(i);
vx.setMatrix(m);
}
// Ksort.sort(f);}*/
for(int i=0;i<g.size();i++){
((Group)g.elementAt(i)).render(r, z, m,l,shad,view);
}
}
public void add(Face[] t,String name) {
if (t==null) return;
if(t.length < 1)return;
Group gr=new Group(t,name,g.size());
g.addElement(gr);
}
public void add(Group gr){
if(gr==null)return;
if(gr.v==null||gr.f==null)return;
if(gr.v.size()<1||gr.f.size()<1)return;
g.addElement(gr);
}
public Group getLast(){
return (Group)g.lastElement();
}
public Vector select(int sx,int sy,int x,int y,Matrix3D m){ // возвращает объекты, попадающие в рамку выделения
if(sx>x){
int tmp=sx;
sx=x;
x=tmp;
}
if(sy>y){
int tmp=sy;
sy=y;
y=tmp;
}
Vector p=new Vector();
if(l!=null)for(int i=0;i<l.size();i++){
Light z=(Light)l.elementAt(i);
if(((z.sx-10>=sx&&z.sx-10<=x)||(z.sx+10>=sx&&z.sx+10<=x)||(z.sx-10<=sx&&z.sx+10>=x))&&((z.sy-10>=sy&&z.sy-10<=y)||(z.sy+10>=sy&&z.sy+10<=y)||(z.sy-10<=sy&&z.sy+10>=y)))p.addElement(z);
}
int[] b;
if(g!=null)for (int i=0;i<g.size();i++){
Group gr=(Group)g.elementAt(i);
b=gr.getBounce(m);
if(((b[0]>=sx&&b[0]<=x)||(b[2]>=sx&&b[2]<=x)||(b[0]<=sx&&b[2]>=x))&&((b[1]>=sy&&b[1]<=y)||(b[3]>=sy&&b[3]<=y)||(b[1]<=sy&&b[3]>=y)))p.addElement(gr);
}
return p;
}
public Vector selectTr(int sx,int sy,int x,int y){ // треугольники
if(sx>x){
int tmp=sx;
sx=x;
x=tmp;
}
if(sy>y){
int tmp=sy;
sy=y;
y=tmp;
}
Vector p=new Vector();
for(int i=0;i<g.size();i++){
Group gr=(Group)g.elementAt(i);
for(int j=0;j<gr.f.size();j++){
Triangle tr=(Triangle)gr.f.elementAt(j);
if((tr.a.sx<=x&&tr.a.sx>=sx&&tr.a.sy<=y&&tr.a.sy>=sy)||(tr.b.sx<=x&&tr.b.sx>=sx&&tr.b.sy<=y&&tr.b.sy>=sy)||(tr.c.sx<=x&&tr.c.sx>=sx&&tr.c.sy<=y&&tr.c.sy>=sy)) p.addElement(tr);
}
}
return p;
}
public Vector selectVer(int sx,int sy,int x,int y){ // вершины
if(sx>x){
int tmp=sx;
sx=x;
x=tmp;
}
if(sy>y){
int tmp=sy;
sy=y;
y=tmp;
}
Vector p=new Vector();
for(int i=0;i<g.size();i++){
Group gr=(Group)g.elementAt(i);
for(int j=0;j<gr.v.size();j++){
Vertex ver=(Vertex)gr.v.elementAt(j);
if(ver.sx>=sx&&ver.sx<=x&&ver.sy>=sy&&ver.sy<=y)p.addElement(ver);
}
}
return p;
}
public Vector select3d(int[] s,Matrix3D m){ // объекты, попавшие в трехмерное выделение
if(s[0]>s[3]){
int tmp=s[0];
s[0]=s[3];
s[3]=tmp;
}
if(s[1]>s[4]){
int tmp=s[1];
s[1]=s[4];
s[4]=tmp;
}
if(s[2]>s[5]){
int tmp=s[2];
s[2]=s[5];
s[5]=tmp;
}
Vector p=new Vector();
if(l!=null)for (int i=0;i<l.size();i++){
Light z=(Light)l.elementAt(i);
if(z.x>=s[0]&&z.x<=s[3]&&z.y>=s[1]&&z.y<=s[4]&&z.z>=s[2]&&z.z<=s[5])p.addElement(z);
}
int[] b;
if(g!=null)for(int i=0;i<g.size();i++){
Group gr=(Group)g.elementAt(i);
b=gr.getVolumeBounce(m);
if(((b[0]>=s[0]&&b[0]<=s[3])||(b[3]>=s[0]&&b[3]<=s[3])||(b[0]<=s[0]&&b[3]>=s[3]))&&((b[1]>=s[1]&&b[1]<=s[4])||(b[4]>=s[1]&&b[4]<=s[4])||(b[1]<=s[1]&&b[4]>=s[4]))&&((b[2]>=s[2]&&b[2]<=s[5])||(b[5]>=s[2]&&b[5]<=s[5])||(b[2]<=s[2]&&b[5]>=s[5]))) p.addElement(gr);
}
return p;
}
public Vector select3dTr(int[] s){
if(s[0]>s[3]){
int tmp=s[0];
s[0]=s[3];
s[3]=tmp;
}
if(s[1]>s[4]){
int tmp=s[1];
s[1]=s[4];
s[4]=tmp;
}
if(s[2]>s[5]){
int tmp=s[2];
s[2]=s[5];
s[5]=tmp;
}
Vector p=new Vector();
for(int i=0;i<g.size();i++){
Group gr=(Group)g.elementAt(i);
for(int j=0;j<gr.f.size();j++){
Triangle tr=(Triangle)gr.f.elementAt(j);
if((tr.a.x<=s[3]&&tr.a.x>=s[0]&&tr.a.y<=s[4]&&tr.a.y>=s[1]&&tr.a.z<=s[5]&&tr.a.z>=s[2])||(tr.b.x<=s[3]&&tr.b.x>=s[0]&&tr.b.y<=s[4]&&tr.b.y>=s[1]&&tr.b.z<=s[5]&&tr.b.z>=s[2])||(tr.c.x<=s[3]&&tr.c.x>=s[0]&&tr.c.y<=s[4]&&tr.c.y>=s[1]&&tr.c.z<=s[5]&&tr.c.z>=s[2])) p.addElement(tr);
}
}
return p;
}
public Vector select3dVer(int[] s){
if(s[0]>s[3]){
int tmp=s[0];
s[0]=s[3];
s[3]=tmp;
}
if(s[1]>s[4]){
int tmp=s[1];
s[1]=s[4];
s[4]=tmp;
}
if(s[2]>s[5]){
int tmp=s[2];
s[2]=s[5];
s[5]=tmp;
}
Vector p=new Vector();
for(int i=0;i<g.size();i++){
Group gr=(Group)g.elementAt(i);
for(int j=0;j<gr.v.size();j++){
Vertex ver=(Vertex)gr.v.elementAt(j);
if(ver.x>=s[0]&&ver.x<=s[3]&&ver.y>=s[1]&&ver.y<=s[4]&&ver.z>=s[2]&&ver.z<=s[5])p.addElement(ver);
}
}
return p;
}
public Object pick(int x,int y,Matrix3D m){ // ближайший объект на месте щелчка курсором
int[] b;
int max=Integer.MAX_VALUE;
Object ret=null;
if(l!=null)for(int i=0;i<l.size();i++){
Light li=(Light)l.elementAt(i);
if(li.zc<=max&&x>=li.sx-10&&x<=li.sx+10&&y>=li.sy-10&&y<=li.sy+10&&li.zc>=(-Vertex.dist+1)){max=li.zc;ret=li;}
}
if(g!=null)for(int i=0;i<g.size();i++){
Group gr=(Group)g.elementAt(i);
b=gr.getBounce(m);
if(b[4]<=max&&x>=b[0]&&x<=b[2]&&y>=b[1]&&y<=b[3]&&b[4]>=(-Vertex.dist+1)){max=b[4];ret=gr;}
}
return ret;
}
public Triangle pickTr(int x,int y,Matrix3D m){
int minz=Integer.MAX_VALUE;
Triangle ret=null;
for (int i=0;i<g.size();i++){
Group gr=(Group)g.elementAt(i);
for(int j=0;j<gr.f.size();j++){
Triangle tr=(Triangle)gr.f.elementAt(j);
tr.setVertexMatrix(m);
int ai=(tr.a.sx - x) * (tr.b.sy - tr.a.sy) - (tr.b.sx - tr.a.sx) * (tr.a.sy - y);
int bi=(tr.b.sx - x) * (tr.c.sy - tr.b.sy) - (tr.c.sx - tr.b.sx) * (tr.b.sy - y);
int ci=(tr.c.sx - x) * (tr.a.sy - tr.c.sy) - (tr.a.sx - tr.c.sx) * (tr.c.sy - y);
if(((ai>=0&&bi>=0&&ci>=0)||(ai<=0&&bi<=0&&ci<=0))&&tr.getS()<minz){ ret=tr;
minz=tr.getS();
}
}
}
return ret;
}
public Vertex pickVer(int x,int y){
int max=Integer.MAX_VALUE;
Vertex ret=null;
for (int i=0;i<g.size();i++){
Group gr=(Group)g.elementAt(i);
for(int j=0;j<gr.v.size();j++){
Vertex ver=(Vertex)gr.v.elementAt(j);
if(Math.abs(ver.sx-x)<=6&&Math.abs(ver.sy-y)<=6&&ver.z<max){
ret=ver;
max=ver.z;
}
}
}
return ret;
}
public void setMaterial(Material m){
if(g==null||g.isEmpty())return;
for(int i=0;i<g.size();i++){
((Group)g.elementAt(i)).setMaterial(m);
}
}
public void deleteFace(Face f){
if(f==null||!(f instanceof Triangle))return;
for(int i=0;i<g.size();i++){
Group gr=(Group)g.elementAt(i);
for(int j=0;j<gr.f.size();j++){
if(gr.f.elementAt(j)==f){ gr.f.removeElementAt(j);
return;
}
}
}
}
public void deleteVertex(Vertex v){
if(v==null)return;
for(int i=0;i<g.size();i++){
Group gr=(Group)g.elementAt(i);
for(int j=0;j<gr.f.size();j++){
Triangle tr=(Triangle)gr.f.elementAt(j);
if(tr.a==v||tr.b==v||tr.c==v){ gr.f.removeElement(tr);
j--;
}
}
gr.v.removeElement(v);
}
}
public void vertexNorm(Vertex v){
int j,i,nn=0;
v.nx=v.ny=v.nz=0;
for(i=0; i<g.size();i++){
Group gr=(Group)g.elementAt(i);
for(j=0;j<gr.f.size();j++){
Triangle tr=(Triangle)gr.f.elementAt(j);
if((v==tr.a||v==tr.b||v==tr.c)&&tr.smooth){
nn++;
v.nz+=tr.nz;
v.nx+=tr.nx;
v.ny+=tr.ny;
}
}
v.nx/=nn;
v.ny/=nn;
v.nz/=nn;
}
}
public void deleteLight(Light lig){
l.removeElement(lig);
}
/* public int containsVertex(Vertex ver) {
boolean r = false;
int i;
for (i = 0; i < v.size(); i++) {
Vertex ve = (Vertex)v.elementAt(i);
r = (ve.x == ver.x) && (ve.y == ver.y) && (ve.z == ver.z);
if (r) break;
}
return (r)?i:-1;
}*/
}

146
src/Saver.java Normal file
View File

@ -0,0 +1,146 @@
// сохранятель в s3d
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import java.io.*;
import java.util.Vector;
import javax.microedition.lcdui.Image;
/**
*
* @author Александр
*/
public class Saver {
public static void saveS3D(Model m,Vector mat,OutputStream os){
int i,j;
try{
DataOutputStream dos=new DataOutputStream(os);
dos.writeInt(0xffff06); //s3d 0.6
dos.writeInt(Main.main.e.name.length());
dos.writeChars(Main.main.e.name);
dos.writeInt(Main.main.e.vendor.length());
dos.writeChars(Main.main.e.vendor);
dos.writeInt(Main.main.e.description.length());
dos.writeChars(Main.main.e.description);
dos.writeInt(mat.size()); //матерьялы
dos.writeInt(m.g==null?0:m.g.size()); //объекты
dos.writeInt(m.l==null?0:m.l.size()); //свет
dos.writeInt(Statics.background); //фон
dos.writeInt(Statics.pers); //перспектива
dos.writeInt(Statics.limit); //предел
for(i=0;i<mat.size();i++){ //все материалы
Material ma=(Material)mat.elementAt(i);
dos.writeInt(ma.desc.length());
dos.writeChars(ma.desc);
dos.writeInt(ma.diffuseColor);
dos.writeInt(ma.opacity);
dos.writeBoolean(ma.doubleSided);
dos.writeBoolean(ma.useFaceColor);
dos.writeFloat(ma.self);
dos.writeFloat(ma.us);
dos.writeFloat(ma.vs);
dos.writeFloat(ma.uo);
dos.writeFloat(ma.vo);
if(ma.texture==null)
dos.writeBoolean(false);
else{
dos.writeBoolean(true);
dos.writeInt(ma.w);
dos.writeInt(ma.h);
int MD=Statics.textureSaving;
dos.writeInt(MD);
if(MD!=2){
//String str="";
ByteArrayOutputStream bas=new ByteArrayOutputStream();
byte[] barray=null;
if(MD==1){
//str=Lib_jpeg.saveimagetostring(Image.createRGBImage(ma.texture, ma.w, ma.h, false), 100);
JpegEncoder je = new JpegEncoder(Image.createRGBImage(ma.texture, ma.w, ma.h, false), 100, bas);
}
else if(MD==0){
//str=Lib_png3.png_to_string(Image.createRGBImage(ma.texture, ma.w, ma.h, false));
barray=Encoder.toPNG(Image.createRGBImage(ma.texture, ma.w, ma.h, false));
}
else if(MD==3){
Lib_gif.init(100);
Lib_gif.add_frame(Image.createRGBImage(ma.texture, ma.w, ma.h, false));
Lib_gif.close(bas);
}
if(MD!=0)barray=bas.toByteArray();
dos.writeInt(barray.length);
dos.write(barray);
barray=null;
//byte[] barray=str.getBytes();
//dos.writeInt(barray.length);
//dos.write(barray);
//barray=null;
//str=null;
bas.flush();
bas.close();
//bas=null;
System.gc();
}
else if(MD==2){
dos.writeInt(ma.texture.length);
for(j=0;j<ma.texture.length;j++){
/*int r=(ma.texture[j]>>16)&0xff,g=(ma.texture[j]>>8)&0xff,b=ma.texture[j]&0xff;
dos.writeInt(r);
dos.writeInt(g);
dos.writeInt(b);*/
dos.writeInt(ma.texture[j]);
}
}
}
}
for(i=0;i<m.g.size();i++){
Group g=(Group)m.g.elementAt(i);
dos.writeInt(g.name.length());
dos.writeChars(g.name);
dos.writeBoolean(g.visible);
dos.writeInt(g.v.size());
for(j=0;j<g.v.size();j++){
Vertex v=(Vertex)g.v.elementAt(j);
dos.writeInt(v.x);
dos.writeInt(v.y);
dos.writeInt(v.z);
dos.writeFloat(v.nx);
dos.writeFloat(v.ny);
dos.writeFloat(v.nz);
}
dos.writeInt(g.f.size());
for(j=0;j<g.f.size();j++){
Triangle t=(Triangle)g.f.elementAt(j);
dos.writeInt(g.v.indexOf(t.a));
dos.writeInt(g.v.indexOf(t.b));
dos.writeInt(g.v.indexOf(t.c));
dos.writeInt(t.color);
dos.writeFloat(t.nx);
dos.writeFloat(t.ny);
dos.writeFloat(t.nz);
dos.writeBoolean(t.smooth);
dos.writeInt(t.material==null?-1:mat.indexOf(t.material));
if(t.uv==null)
dos.writeBoolean(false);
else{
dos.writeBoolean(true);
dos.writeFloat(t.uv[0]);
dos.writeFloat(t.uv[1]);
dos.writeFloat(t.uv[2]);
dos.writeFloat(t.uv[3]);
dos.writeFloat(t.uv[4]);
dos.writeFloat(t.uv[5]);
}
}
}
if(m.l!=null)for(i=0;i<m.l.size();i++){
Light l=(Light)m.l.elementAt(i);
dos.writeInt(l.x);
dos.writeInt(l.y);
dos.writeInt(l.z);
}
dos.flush();
dos.close();
}catch(Exception e){}
}
}

186
src/StartWindow.java Normal file
View File

@ -0,0 +1,186 @@
// начальное окно выбора языка и других настроек
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import javax.microedition.lcdui.*;
/**
*
* @author Александр
*/
public class StartWindow extends Canvas{
int w,h,wind=0,i;
Image im;
public StartWindow(){
setFullScreenMode(true);
w=getWidth();
h=getHeight();
}
public void paint(Graphics g){
g.setFont(Statics.font);
g.setColor(Statics.menuBack);
g.fillRect(0, 0, w, h);
if(wind==0){
g.setColor(0x555555);
g.drawString(Statics.russian?"Выбери язык":"Choose language", w/2, 3, 17);
g.setColor(Statics.textColor);
g.drawString(Statics.russian?"Выбери язык":"Choose language", w/2-1, 3, 17);
int ssh=g.getFont().getHeight();
String s="Русский";
if(i==0)g.setColor(0xbb3333); else g.setColor(0x8888ff);
g.fillRoundRect(w/2-g.getFont().stringWidth(s)/2, h/2-ssh, g.getFont().stringWidth(s)+5, ssh,10,10);
g.setColor(0);
g.drawRoundRect(w/2-g.getFont().stringWidth(s)/2, h/2-ssh, g.getFont().stringWidth(s)+5, ssh,10,10);
g.setColor(0x555555);
g.drawString(s, w/2+2, h/2-ssh, 17);
g.setColor(Statics.textColor);
g.drawString(s, w/2+3, h/2-ssh, 17);
s="English";
if(i==1)g.setColor(0xbb3333); else g.setColor(8947967);
g.fillRoundRect(w/2-g.getFont().stringWidth(s)/2, h/2+2, g.getFont().stringWidth(s)+5, ssh,10,10);
g.setColor(0);
g.drawRoundRect(w/2-g.getFont().stringWidth(s)/2, h/2+2, g.getFont().stringWidth(s)+5, ssh,10,10);
g.setColor(0x555555);
g.drawString(s, w/2+2, h/2+2, 17);
g.setColor(Statics.textColor);
g.drawString(s, w/2+3, h/2+2, 17);
drawLeftSoft(g,"Ok");
}
else if(wind==1){
g.setColor(0x555555);
g.drawString(Statics.russian?"Сенсорный ввод?":"Use touch input?", w/2, 3, 17);
g.setColor(Statics.textColor);
g.drawString(Statics.russian?"Сенсорный ввод?":"Use touch input?", w/2-1, 3, 17);
g.setColor(8947967);
g.fillRoundRect(w/4, h/4,w/2, h/2,40,40);
g.setColor(0);
g.drawRoundRect(w/4, h/4,w/2, h/2,40,40);
g.setColor(0x555555);
g.drawString(Statics.russian?"Дотронься до экрана":"Touch screen", w/2, h/2, 17);
g.setColor(Statics.textColor);
g.drawString(Statics.russian?"Дотронься до экрана":"Touch screen", w/2-1, h/2-1, 17);
drawLeftSoft(g,Statics.russian?"Нет!Только кнопки только хардкор!":"No!It's push-button phone");
}
else if(wind==2){
g.setColor(0x555555);
g.drawString(Statics.russian?"Размер иконок":"Size of icons", w/2, 3, 17);
g.setColor(Statics.textColor);
g.drawString(Statics.russian?"Размер иконок":"Size of icons", w/2-1, 3, 17);
if((im==null||(im!=null&&im.getWidth()!=60))&&Statics.bigImages){
try{
im=Image.createImage("/img/60/box.png");
}catch(Exception ioe){}
}
if((im==null||(im!=null&&im.getWidth()!=30))&&!Statics.bigImages){
try{
im=Image.createImage("/img/30/box.png");
}catch(Exception ioe){}
}
g.drawImage(im, w/2, h/2-im.getHeight()/2, 17);
g.drawString((Statics.bigImages?"60x60":"30x30"), w/2, h/2+im.getHeight()/2+10, 17);
g.setColor(8947967);
g.fillRoundRect(w-w/4, h/2-20,w/4, 40,20,20);
g.fillRoundRect(0, h/2-20,w/4, 40,20,20);
if(Statics.touch)g.fillRoundRect(w/2-w/6, h-h/4,w/3, 30,20,20);
g.setColor(0);
g.drawRoundRect(w-w/4, h/2-20,w/4, 40,20,20);
g.drawRoundRect(0, h/2-20,w/4, 40,20,20);
g.setColor(Statics.textColor);
g.drawString(">", w-w/4+15, h/2-10, 17);
g.drawString("<", w/4-15, h/2-10, 17);
if(Statics.touch)g.drawString("Ok", w/2, h-h/4+10, 17);
else drawLeftSoft(g,"Ok");
}
repaint();
}
private void drawLeftSoft(Graphics g,String s){
int ssh=g.getFont().getHeight();
g.setColor(8947967);
g.fillRoundRect(0, getHeight() - ssh+1, g.getFont().stringWidth(s)+5, ssh-1,10,10);
g.setColor(0);
g.drawRoundRect(0, getHeight() - ssh+1, g.getFont().stringWidth(s)+5, ssh-2,10,10);
g.setColor(0x555555);
g.drawString(s, 2, h - 2, 36);
g.setColor(Statics.textColor);
g.drawString(s, 3, h - 1, 36);
}
public void keyPressed(int key){
if(wind==2){
int ga=getGameAction(key);
switch(ga){
case LEFT:
case RIGHT: Statics.bigImages=!Statics.bigImages;break;
case FIRE: Main.main.toMenu();break;
}
}
if(wind==0){
int ga=getGameAction(key);
switch(ga){
case UP: i--; if(i<0)i=1;break;
case DOWN: i++; if(i>1)i=0;break;
case FIRE: Statics.russian=(i==0); wind=1;break;
}
}
String strCode = null;
try {
strCode = getKeyName(key).toLowerCase();
}
catch (IllegalArgumentException e) {
}
if (strCode != null)
{
if (((("soft1".equals(strCode)) || ("soft 1".equals(strCode)) || ("soft_1".equals(strCode)) || ("softkey 1".equals(strCode)) || ("sk2(left)".equals(strCode)) || (strCode.startsWith("left soft")))))
{ if(wind==0)wind=1; else if(wind==1)wind=2; else{if(!Statics.bigImages)Statics.font=Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM); Main.main.toMenu();}}//left
/*if (("soft2".equals(strCode)) || ("soft 2".equals(strCode)) || ("soft_2".equals(strCode)) || ("softkey 4".equals(strCode)) || ("sk1(right)".equals(strCode)) || (strCode.startsWith("right soft")))
{fire(); }//right*/
}
switch (key)
{
case -202:
case -21:
case -6:
case 21:
case 105:
case 113:
case 57345:
if(wind==0){wind=1; Statics.russian=(i==0); } else if(wind==1) wind=2; else{if(!Statics.bigImages)Statics.font=Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM); Main.main.toMenu(); }break;//left
/*case -203:
case -22:
case -7:
case 22:
case 106:
case 112:
case 57346:
fire();break;//right*/
}
}
protected void pointerDragged(int x,int y){
if(wind==0){if(y>h/2)i=1; else i=0; }
}
protected void pointerReleased(int x,int y){
if(wind==0){Statics.russian=(i==0);wind=1; }
}
protected void pointerPressed(int x,int y){
if(wind==0){
if(y>h/2)i=1; else i=0;
}
else if(wind==1){
Statics.touch=true;
wind=2;
}
else if(wind==2){
if(x>w-w/4||x<w/4){Statics.bigImages=!Statics.bigImages;}
else{if(Statics.bigImages)Statics.font=Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_LARGE); Main.main.toMenu();}
}
}
}

16
src/Statics.java Normal file
View File

@ -0,0 +1,16 @@
// Глобальные настройки и поля
import javax.microedition.lcdui.Font;
public class Statics
{
static int w = 240; // размеры экрана
static int h = 320;
static int pers=300; // перспектива
static int limit=20000; // дальний предел видимости
static int textureSaving=1; // формат сохранения текстур
// static int sleep = 0;
static Font font=Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM); // шрифт
static int menuBack=0x9d9a9c,edBack=0xbdbabc,curColor=0xff0000,textColor=0xeeeaec,gridColor=0xdddddd,menuTextColor=0x99,background=0; // цвета
static boolean touch=false,bigImages=false,russian=true,extraBuffers=false,randColor=false,grid=true; // сенсорный экран, большие иконки, русский язык, дополнительные буферы, случайный цвет новых объектов, сетка
}

467
src/Triangle.java Normal file
View File

@ -0,0 +1,467 @@
// треугольник. собсно, полигон
import javax.microedition.lcdui.Graphics;
import java.util.Vector;
public class Triangle extends Face
{
public Vertex a; // вершины
public Vertex b;
public Vertex c;
public float nx; // нормаль
public float ny;
public float nz;
public float rnx,rny,rnz;
public float k;
public boolean smooth=true; // сглаживать ли с соседними
public Material material=null; // материал
public float[] uv; // текстурные координаты
public Triangle(Vertex v1, Vertex v2, Vertex v3, int col)
{
a = v1;
b = v2;
c = v3;
color = col;
}
public void norm(){ //рассчет и нормирование нормалей
float tnx = (a.y - b.y) * (a.z - c.z) - (a.z - b.z) * (a.y - c.y);
float tny = (a.z - b.z) * (a.x - c.x) - (a.x - b.x) * (a.z - c.z);
float tnz = (a.x - b.x) * (a.y - c.y) - (a.y - b.y) * (a.x - c.x);
double length = Math.sqrt(tnx * tnx + tny * tny + tnz * tnz);
tnx = (float)(tnx / ((length == 0D) ? 1D : length));
tny = (float)(tny / ((length == 0D) ? 1D : length));
tnz = (float)(tnz / ((length == 0D) ? 1D : length));
rnx= nx = tnx;
rny= ny = tny;
rnz = nz = tnz; }
public void norm(float x,float y,float z){
rnx=nx=x;
rny=ny=y;
rnz=nz=z;
}
public void setUV(float[] in){
uv=in;
}
public void setUV(){
uv=new float[]{a.u,a.v,b.u,b.v,c.u,c.v};
}
public void invert(){
nx*=-1;
ny*=-1;
nz*=-1;
}
public int getS() {
return ((a.zc + b.zc + c.zc) / 3);
}
public void paintFlat(Graphics g){
paint(g,color,0);
}
public void paint(Graphics g,int v)
{
int rc = color >> 16 & 0xFF; int gc = color >> 8 & 0xFF; int bc = color & 0xFF;
rc = (int)(rc * -k);
gc = (int)(gc * -k);
bc = (int)(bc * -k);
paint(g, rc << 16 | gc << 8 | bc,v);
}
// col - цвет, v - обзор: перспективный или один из боковых
public void paint(Graphics g, int col,int v) {
double dis=1;
g.setColor(col);
if(v!=0){
dis=(double)Main.main.e.dist;
if(dis>0)dis=(dis/10000)+0.1;
else if(dis==0)dis=0.1;
else dis=0.1+dis/100000;
}
if(v==0)g.fillTriangle(a.sx, a.sy, b.sx, b.sy, c.sx, c.sy);
else if(v==1){
int x0=Main.main.e.xo;
int z0=Main.main.e.zo;
// int scale=1;
g.fillTriangle((int)(Statics.w/2+x0*dis+a.x*dis),(int)(Statics.h/2-z0*dis-a.z*dis),(int)(Statics.w/2+x0*dis+b.x*dis),(int)(Statics.h/2-z0*dis-b.z*dis),(int)(Statics.w/2+x0*dis+c.x*dis),(int)(Statics.h/2-z0*dis-c.z*dis));
}
else if(v==2){
int y0=Main.main.e.yo;
int z0=Main.main.e.zo;
//int scale=1;
g.fillTriangle((int)(Statics.w/2+z0*dis+a.z*dis),(int)(Statics.h/2-y0*dis-a.y*dis),(int)(Statics.w/2+z0*dis+b.z*dis),(int)(Statics.h/2-y0*dis-b.y*dis),(int)(Statics.w/2+z0*dis+c.z*dis),(int)(Statics.h/2-y0*dis-c.y*dis));
}
else if(v==3){
int y0=Main.main.e.yo;
int x0=Main.main.e.xo;
// int scale=1;
g.fillTriangle((int)(Statics.w/2+x0*dis+a.x*dis),(int)(Statics.h/2-y0*dis-a.y*dis),(int)(Statics.w/2+x0*dis+b.x*dis),(int)(Statics.h/2-y0*dis-b.y*dis),(int)(Statics.w/2+x0*dis+c.x*dis),(int)(Statics.h/2-y0*dis-c.y*dis));
}
}
public void setVertexMatrix(Matrix3D m) {
a.setMatrix(m);
b.setMatrix(m);
c.setMatrix(m);
}
public boolean isVisible(int v){ // проверка полигона на видимость
if(v==0){
if(a.zc<-Vertex.dist&&b.zc<-Vertex.dist&&c.zc<-Vertex.dist) return false;
if(a.zc>Statics.limit&&b.zc>Statics.limit&&c.zc>Statics.limit) return false;
if((a.sx<0&&b.sx<0&&c.sx<0)||(a.sx>Statics.w&&b.sx>Statics.w&&c.sx>Statics.w))return false;
if((a.sy<0&&b.sy<0&&c.sy<0)||(a.sy>Statics.h&&b.sy>Statics.h&&c.sy>Statics.h)) return false;
if(material!=null&&material.doubleSided)return true;
if(/*(material==null||material.opacity==255)&&*/rnz>0)return false;
}
else{
double dis=(double)Main.main.e.dist;
if(dis>0)dis=dis/10000+0.1;
else if(dis==0)dis=0.1;
else dis=0.1+dis/100000;
int x0=Main.main.e.xo;
int z0=Main.main.e.zo;
int y0=Main.main.e.yo;
int w=Statics.w,h=Statics.h;
if(((a.x*dis+x0*dis<-w/2&&b.x*dis+x0*dis<-w/2&&c.x*dis+x0*dis<-w/2)||(a.x*dis+x0*dis>w/2&&b.x*dis+x0*dis>w/2&&c.x*dis+x0*dis>w/2))&&(v==1||v==3))return false;
if(((a.z*dis+z0*dis<-h/2&&b.z*dis+z0*dis<-h/2&&c.z*dis+z0*dis<-h/2)||(a.z*dis+z0*dis>h/2&&b.z*dis+z0*dis>h/2&&c.z*dis+z0*dis>h/2))&&v==1)return false;
if(((a.z*dis+z0*dis<-w/2&&b.z*dis+z0*dis<-w/2&&c.z*dis+z0*dis<-w/2)||(a.z*dis+z0*dis>w/2&&b.z*dis+z0*dis>w/2&&c.z*dis+z0*dis>w/2))&&v==2)return false;
if(((a.y*dis+y0*dis<-h/2&&b.y*dis+y0*dis<-h/2&&c.y*dis+y0*dis<-h/2)||(a.y*dis+y0*dis>h/2&&b.y*dis+y0*dis>h/2&&c.y*dis+y0*dis>h/2))&&(v==3||v==2))return false;
}
return true;
}
public void setMatrix(Matrix3D m)
{
rnx = (nx * m.xx + ny * m.xy + nz * m.xz);
rny = (nx * m.yx + ny * m.yy + nz * m.yz);
rnz = (nx * m.zx + ny * m.zy + nz * m.zz);
}
public void soequal(){
nx=rnx;
ny=rny;
nz=rnz;
double length = Math.sqrt(nx * nx + ny * ny + nz * nz);
nx = (float)(nx / ((length == 0D) ? 1D : length));
ny = (float)(ny / ((length == 0D) ? 1D : length));
nz = (float)(nz / ((length == 0D) ? 1D : length));
}
public void light(Vector l){ // рассчет освещения при отключенном сглаживании (все точки треугольника освещены одинаково)
if(l!=null&&!l.isEmpty()){
int mx=(a.xc+b.xc+c.xc)/3;
int my=(a.yc+b.yc+c.yc)/3;
k=0;
float kk;
for(int i=0;i<l.size();i++){
if(l.elementAt(i)==null)continue;
Light li=(Light)l.elementAt(i);
float lx=mx-li.xc,ly=my-li.yc,lz=getS()-li.zc;
double len=Math.sqrt(lx*lx+ly*ly+lz*lz);
lx/=len;
ly/=len;
lz/=len;
kk=(lx*rnx+ly*rny+lz*rnz);
if(kk>0){if(material!=null&&material.doubleSided)kk=-kk; else kk=0;}
kk*=li.s;
k+=kk;
}
}
else{
k=rnz;
if(k>0){if(material!=null&&material.doubleSided)k=-k; else k=0;}
}
}
// рендеринг полигона. r - экранный буфер, z - буфер глубины, s - тип шейдинга, v - обзор
public void render(int[] r,int[] z,int s,int v){
if(v!=0){
switch(v){
case 1: top(r,z,s);break;
case 2: right(r,z,s);break;
case 3: front(r,z,s);break;
}
return;
}
byte culling=0; // проверка на залезание треугольника за экран, т.е. когда одна или две из вершин по Z < 0.
//В этом случае треугольник разбивается на два и один подтреугольники соответственно для корректного просчета координат вершин, но искажений исбежать все равно не удалось. Печальбеда.
Vertex ver1=null,ver2=null,ver3=null,ver4=null,ver5=null;
if(a.zc<-Vertex.dist&&b.zc>-Vertex.dist&&c.zc>-Vertex.dist||b.zc<-Vertex.dist&&a.zc>-Vertex.dist&&c.zc>-Vertex.dist||c.zc<-Vertex.dist&&a.zc>-Vertex.dist&&b.zc>-Vertex.dist){
culling=1;
if(a.zc<-Vertex.dist){ver1=a;ver2=b;ver3=c;if(uv!=null){ver2.u=uv[2];ver2.v=uv[3];ver3.u=uv[4];ver3.v=uv[5];} }
else if(b.zc<-Vertex.dist){ver1=b;ver2=a;ver3=c;if(uv!=null){ver2.u=uv[0];ver2.v=uv[1];ver3.u=uv[4];ver3.v=uv[5];} }
else{ ver1=c;ver2=a;ver3=b;if(uv!=null){ver2.u=uv[0];ver2.v=uv[1];ver3.u=uv[2];ver3.v=uv[3];} }
ver4=new Vertex();
ver5=new Vertex();
ver4.zc=-Vertex.dist+1;
ver5.zc=-Vertex.dist+1;
ver4.xc=ver2.xc + (ver1.xc - ver2.xc) * (-Vertex.dist+1 - ver2.zc) / (ver1.zc - ver2.zc);
ver4.yc=ver2.yc + (ver1.yc - ver2.yc) * (-Vertex.dist+1 - ver2.zc) / (ver1.zc - ver2.zc);
ver4.k=ver2.k + (ver1.k - ver2.k) * (-Vertex.dist+1 - ver2.zc) / (ver1.zc - ver2.zc);
ver4.u=ver2.u + (ver1.u - ver2.u) * (-Vertex.dist+1 - ver2.zc) / (ver1.zc - ver2.zc);
ver4.v=ver2.v + (ver1.v - ver2.v) * (-Vertex.dist+1 - ver2.zc) / (ver1.zc - ver2.zc);
ver5.xc=ver3.xc + (ver1.xc - ver3.xc) * (-Vertex.dist+1 - ver3.zc) / (ver1.zc - ver3.zc);
ver5.yc=ver3.yc + (ver1.yc - ver3.yc) * (-Vertex.dist+1 - ver3.zc) / (ver1.zc - ver3.zc);
ver5.k=ver3.k + (ver1.k - ver3.k) * (-Vertex.dist+1 - ver3.zc) / (ver1.zc - ver3.zc);
ver5.u=ver3.u + (ver1.u - ver3.u) * (-Vertex.dist+1 - ver3.zc) / (ver1.zc - ver3.zc);
ver5.v=ver3.v + (ver1.v - ver3.v) * (-Vertex.dist+1 - ver3.zc) / (ver1.zc - ver3.zc);
ver4.to2d();
ver5.to2d();
}
if(a.zc<-Vertex.dist&&b.zc<-Vertex.dist||a.zc<-Vertex.dist&&c.zc<-Vertex.dist||b.zc<-Vertex.dist&&c.zc<-Vertex.dist){
if(a.zc>-Vertex.dist){ver1=a;ver2=b;ver3=c;if(uv!=null){ver2.u=uv[2];ver2.v=uv[3];ver3.u=uv[4];ver3.v=uv[5];} }
else if(b.zc>-Vertex.dist){ver1=b;ver2=a;ver3=c;if(uv!=null){ver2.u=uv[0];ver2.v=uv[1];ver3.u=uv[4];ver3.v=uv[5];} }
else{ver1=c;ver2=a;ver3=b;if(uv!=null){ver2.u=uv[0];ver2.v=uv[1];ver3.u=uv[2];ver3.v=uv[3];} }
ver4=new Vertex();
ver5=new Vertex();
ver4.zc=-Vertex.dist+1;
ver5.zc=-Vertex.dist+1;
ver4.xc=ver2.xc + (ver1.xc - ver2.xc) * (-Vertex.dist+1 - ver2.zc) / (ver1.zc - ver2.zc);
ver4.yc=ver2.yc + (ver1.yc - ver2.yc) * (-Vertex.dist+1 - ver2.zc) / (ver1.zc - ver2.zc);
ver4.k=ver2.k + (ver1.k - ver2.k) * (-Vertex.dist+1 - ver2.zc) / (ver1.zc - ver2.zc);
ver4.u=ver2.u + (ver1.u - ver2.u) * (-Vertex.dist+1 - ver2.zc) / (ver1.zc - ver2.zc);
ver4.v=ver2.v + (ver1.v - ver2.v) * (-Vertex.dist+1 - ver2.zc) / (ver1.zc - ver2.zc);
ver5.xc=ver3.xc + (ver1.xc - ver3.xc) * (-Vertex.dist+1 - ver3.zc) / (ver1.zc - ver3.zc);
ver5.yc=ver3.yc + (ver1.yc - ver3.yc) * (-Vertex.dist+1 - ver3.zc) / (ver1.zc - ver3.zc);
ver5.k=ver3.k + (ver1.k - ver3.k) * (-Vertex.dist+1 - ver3.zc) / (ver1.zc - ver3.zc);
ver5.u=ver3.u + (ver1.u - ver3.u) * (-Vertex.dist+1 - ver3.zc) / (ver1.zc - ver3.zc);
ver5.v=ver3.v + (ver1.v - ver3.v) * (-Vertex.dist+1 - ver3.zc) / (ver1.zc - ver3.zc);
ver4.to2d();
ver5.to2d();
culling=2;}
if(s==0){
if(material==null){
int rc = color >> 16 & 0xFF; int gc = color >> 8 & 0xFF; int bc = color & 0xFF;
rc = (int)(rc * -k);
if(rc>255)rc=255;
if(rc<0)rc=0;
gc = (int)(gc * -k);
if(gc>255)gc=255;
if(gc<0)gc=0;
bc = (int)(bc * -k);
if(bc>255)bc=255;
if(bc<0)bc=0;
if(culling==0)
renderFlatTriangle(r,z,a,b,c,rc << 16 | gc << 8 | bc);
else if(culling==1){
renderFlatTriangle(r,z,ver3,ver2,ver4,rc << 16 | gc << 8 | bc);
renderFlatTriangle(r,z,ver3,ver4,ver5,rc << 16 | gc << 8 | bc);
}
else renderFlatTriangle(r,z,ver1,ver4,ver5,rc << 16 | gc << 8 | bc);
}
else{
if(material.texture==null||material.useFaceColor){
int rc = (material.useFaceColor?color:material.diffuseColor) >> 16 & 0xFF; int gc = (material.useFaceColor?color:material.diffuseColor) >> 8 & 0xFF; int bc = (material.useFaceColor?color:material.diffuseColor) & 0xFF;
rc = (int)(rc * -k);
if(rc>255)rc=255;
if(rc<0)rc=0;
gc = (int)(gc * -k);
if(gc>255)gc=255;
if(gc<0)gc=0;
bc = (int)(bc * -k);
if(bc>255)bc=255;
if(bc<0)bc=0;
if(culling==0)renderFlatTriangle(r,z,a,b,c,rc << 16 | gc << 8 | bc);
else if(culling==1){renderFlatTriangle(r,z,ver3,ver2,ver4,rc << 16 | gc << 8 | bc);
renderFlatTriangle(r,z,ver3,ver4,ver5,rc << 16 | gc << 8 | bc);
}
else renderFlatTriangle(r,z,ver1,ver4,ver5,rc << 16 | gc << 8 | bc);
}
else{
if(uv!=null){
if(culling==0)renderAffineTexturedTriangle(material,r,z,uv,a,b,c,-k);
else if(culling==1){renderAffineTexturedTriangle(material,r,z,uv,ver3,ver2,ver4,-k);
renderAffineTexturedTriangle(material,r,z,uv,ver3,ver4,ver5,-k);}
else renderAffineTexturedTriangle(material,r,z,uv,ver1,ver4,ver5,-k);
}
else{
if(culling==0)renderAffineTexturedTriangle(material,r,z,a,b,c,-k);
else if(culling==1){renderAffineTexturedTriangle(material,r,z,ver3,ver2,ver4,-k);
renderAffineTexturedTriangle(material,r,z,ver3,ver4,ver5,-k);}
else renderAffineTexturedTriangle(material,r,z,ver1,ver4,ver5,-k);
}
}
}
}
else if(s==1){
if(material==null){
if(!smooth){
int rc = color >> 16 & 0xFF; int gc = color >> 8 & 0xFF; int bc = color & 0xFF;
rc = (int)(rc * -k);
if(rc>255)rc=255;
if(rc<0)rc=0;
gc = (int)(gc * -k);
if(gc>255)gc=255;
if(gc<0)gc=0;
bc = (int)(bc * -k);
if(bc>255)bc=255;
if(bc<0)bc=0;
if(culling==0)
renderFlatTriangle(r,z,a,b,c,rc << 16 | gc << 8 | bc);
else if(culling==1){
renderFlatTriangle(r,z,ver3,ver2,ver4,rc << 16 | gc << 8 | bc);
renderFlatTriangle(r,z,ver3,ver4,ver5,rc << 16 | gc << 8 | bc);
}
else renderFlatTriangle(r,z,ver1,ver4,ver5,rc << 16 | gc << 8 | bc);
}
else{
if(culling==0)
renderTriangle(r,z,a,b,c,color);
else if(culling==1){
renderTriangle(r,z,ver3,ver2,ver4,color);
renderTriangle(r,z,ver3,ver4,ver5,color);
}
else renderTriangle(r,z,ver1,ver4,ver5,color);
}
}
else{
if(material.texture==null||material.useFaceColor){
if(!smooth){
int rc = (material.useFaceColor?color:material.diffuseColor) >> 16 & 0xFF; int gc = (material.useFaceColor?color:material.diffuseColor) >> 8 & 0xFF; int bc = (material.useFaceColor?color:material.diffuseColor) & 0xFF;
int rrc = (int)(rc * -k+rc*material.self);
if(rrc>rc)rrc=rc;
if(rc<0)rc=0;
int rgc = (int)(gc * -k+gc*material.self);
if(rgc>gc)rgc=gc;
if(gc<0)gc=0;
int rbc = (int)(bc * -k+bc*material.self);
if(rbc>bc)rbc=bc;
if(bc<0)bc=0;
if(culling==0)renderFlatTriangle(r,z,a,b,c,rrc << 16 | rgc << 8 | rbc,material.opacity);
else if(culling==1){renderFlatTriangle(r,z,ver3,ver2,ver4,rrc << 16 | rgc << 8 | rbc,material.opacity);
renderFlatTriangle(r,z,ver3,ver4,ver5,rrc << 16 | rgc << 8 | rbc,material.opacity);
}
else renderFlatTriangle(r,z,ver1,ver4,ver5,rrc << 16 | rgc << 8 | rbc,material.opacity);
}
else{
int col=0;
if(material.useFaceColor){
col=material.diffuseColor;
material.diffuseColor=color;}
if(culling==0)renderTriangle(r,z,a,b,c,material);
else if(culling==1){renderTriangle(r,z,ver3,ver2,ver4,material);
renderTriangle(r,z,ver3,ver4,ver5,material);
}
else renderTriangle(r,z,ver1,ver4,ver5,material);
if(material.useFaceColor)material.diffuseColor=col;
}
}
else{
if(!smooth){
if(uv!=null){
if(culling==0)renderAffineTexturedTriangle(material,r,z,uv,a,b,c,-k);
else if(culling==1){renderAffineTexturedTriangle(material,r,z,uv,ver3,ver2,ver4,-k);
renderAffineTexturedTriangle(material,r,z,uv,ver3,ver4,ver5,-k);}
else renderAffineTexturedTriangle(material,r,z,uv,ver1,ver4,ver5,-k);
}
else{
if(culling==0)renderAffineTexturedTriangle(material,r,z,a,b,c,-k);
else if(culling==1){renderAffineTexturedTriangle(material,r,z,ver3,ver2,ver4,-k);
renderAffineTexturedTriangle(material,r,z,ver3,ver4,ver5,-k);}
else renderAffineTexturedTriangle(material,r,z,ver1,ver4,ver5,-k);
}
}
else{
if(uv!=null){
if(culling==0)renderAffineTexturedTriangle(material,r,z,uv,a,b,c);
else if(culling==1){renderAffineTexturedTriangle(material,r,z,uv,ver3,ver2,ver4);
renderAffineTexturedTriangle(material,r,z,uv,ver3,ver4,ver5);}
else renderAffineTexturedTriangle(material,r,z,uv,ver1,ver4,ver5);
}
else{
if(culling==0)renderAffineTexturedTriangle(material,r,z,a,b,c);
else if(culling==1){renderAffineTexturedTriangle(material,r,z,ver3,ver2,ver4);
renderAffineTexturedTriangle(material,r,z,ver3,ver4,ver5);}
else renderAffineTexturedTriangle(material,r,z,ver1,ver4,ver5);
}
}
}
}
}
else if(s==2){
if(culling==0)renderFlatTriangle(r,z,a,b,c,color);
else if(culling==1){renderFlatTriangle(r,z,ver3,ver2,ver4,color);
renderFlatTriangle(r,z,ver3,ver5,ver4,color);
}
else renderFlatTriangle(r,z,ver1,ver5,ver4,color);
}
else if(s==3){
if(culling==0){
drawLine(r,z,a,b,color);
drawLine(r,z,a,c,color);
drawLine(r,z,b,c,color);}
else if(culling==1){renderFlatTriangle(r,z,ver3,ver2,ver4,color);
renderFlatTriangle(r,z,ver3,ver5,ver4,color);
drawLine(r,z,ver3,ver2,color);
drawLine(r,z,ver3,ver5,color);
drawLine(r,z,ver2,ver4,color);
// drawLine(r,z,ver4,ver5,color);
}
else{ renderFlatTriangle(r,z,ver1,ver5,ver4,color);
drawLine(r,z,ver1,ver5,color);
drawLine(r,z,ver1,ver4,color);
// drawLine(r,z,ver4,ver5,color);
}
}
}
private void top(int[] r,int[] z,int s){
int x0=Main.main.e.xo;
int z0=Main.main.e.zo;
double scale=(double)Main.main.e.dist;
if(scale>0)scale=scale/10000+0.1;
else if(scale==0)scale=0.1;
else scale=0.1+scale/100000;
render(r,(int)(Statics.w/2+x0*scale+a.x*scale),(int)(Statics.h/2-z0*scale-a.z*scale),(int)(Statics.w/2+x0*scale+b.x*scale),(int)(Statics.h/2-z0*scale-b.z*scale),(int)(Statics.w/2+x0*scale+c.x*scale),(int)(Statics.h/2-z0*scale-c.z*scale),s);
}
private void right(int[] r,int[] z,int s){
int y0=Main.main.e.yo;
int z0=Main.main.e.zo;
double scale=(double)Main.main.e.dist;
if(scale>0)scale=scale/10000+0.1;
else if(scale==0)scale=0.1;
else scale=0.1+scale/100000;
render(r,(int)(Statics.w/2+z0*scale+a.z*scale),(int)(Statics.h/2-y0*scale-a.y*scale),(int)(Statics.w/2+z0*scale+b.z*scale),(int)(Statics.h/2-y0*scale-b.y*scale),(int)(Statics.w/2+z0*scale+c.z*scale),(int)(Statics.h/2-y0*scale-c.y*scale),s);
}
private void front(int[] r,int[] z,int s){
int y0=Main.main.e.yo;
int x0=Main.main.e.xo;
double scale=(double)Main.main.e.dist;
if(scale>0)scale=scale/10000+0.1;
else if(scale==0)scale=0.1;
else scale=0.1+scale/100000;
render(r,(int)(Statics.w/2+x0*scale+a.x*scale),(int)(Statics.h/2-y0*scale-a.y*scale),(int)(Statics.w/2+x0*scale+b.x*scale),(int)(Statics.h/2-y0*scale-b.y*scale),(int)(Statics.w/2+x0*scale+c.x*scale),(int)(Statics.h/2-y0*scale-c.y*scale),s);
}
private void render(int[] r,int asx,int asy,int bsx,int bsy,int csx,int csy,int s){
if(s==0||s==1){
int rc = color >> 16 & 0xFF; int gc = color >> 8 & 0xFF; int bc = color & 0xFF;
rc = (int)(rc * -k);
if(rc>255)rc=255;
if(rc<0)rc=0;
gc = (int)(gc * -k);
if(gc>255)gc=255;
if(gc<0)gc=0;
bc = (int)(bc * -k);
if(bc>255)bc=255;
if(bc<0)bc=0;
renderTriangle(r,asx,asy,bsx,bsy,csx,csy,rc << 16 | gc << 8 | bc);
}
else if(s==2){
renderTriangle(r,asx,asy,bsx,bsy,csx,csy,color);
}
else if(s==3){
drawLine(r,asx,asy,bsx,bsy,color);
drawLine(r,asx,asy,csx,csy,color);
drawLine(r,bsx,bsy,csx,csy,color);
}
}
}

151
src/Vertex.java Normal file
View File

@ -0,0 +1,151 @@
import java.util.Vector;
/**
* Вершина
* @author Shaman
*/
public class Vertex {
public int sx, sy;
public int xc, yc, zc;
public int x, y, z;
public float nx, ny, nz;
public float rnx, rny, rnz;
public int k;
public float u, v;
public static int dist = 3000;
public Vertex() {
}
public Vertex(int a1, int a2, int a3) {
xc = (x = a1);
yc = (y = a2);
zc = (z = a3);
to2d();
}
public Vertex(Vertex vertex) {
x = vertex.x;
y = vertex.y;
z = vertex.z;
nx = vertex.nx;
ny = vertex.ny;
nz = vertex.nz;
xc = vertex.xc;
yc = vertex.yc;
zc = vertex.zc;
u = vertex.u;
v = vertex.u;
to2d();
}
public void sn(float rx, float ry, float rz) {
nx = rx;
ny = ry;
nz = rz;
}
public void setUV(float a, float b) {
u = a;
v = b;
}
public void setMatrix(Matrix3D m) {
xc = (int) (x * m.xx + y * m.xy + z * m.xz);
yc = (int) (x * m.yx + y * m.yy + z * m.yz);
zc = (int) (x * m.zx + y * m.zy + z * m.zz);
xc += (int) m.xo;
yc += (int) m.yo;
zc += (int) m.zo;
rnx = (nx * m.xx + ny * m.xy + nz * m.xz);
rny = (nx * m.yx + ny * m.yy + nz * m.yz);
rnz = (nx * m.zx + ny * m.zy + nz * m.zz);
to2d();
}
public final void to2d() {
if (zc == -dist) {
zc = -dist + 1;
}
if (zc > -dist) { // Здесь я пытался решить рассчет координат точек при Z < 0, ведь в этом случае они ведут себя неправильно, но так и не смог и оставил обычные формулы рассчета проекции.
// int z2 = (zc > -dist) ? zc : -dist-1;
int z2 = zc + dist;
sx = (Statics.w / 2 + xc * Statics.pers / z2);
sy = (Statics.h / 2 - yc * Statics.pers / z2);
}
/* else if(zc<-dist){
int z2=zc+dist;
sx = (Statics.w / 2 - xc*z2/Statics.pers);
sy = (Statics.h / 2 + yc*z2/Statics.pers);
}*/
/* else{
sx = (Statics.w / 2 + xc);//*Statics.pers/5);
sy = (Statics.h / 2 - yc);//*Statics.pers/5);
}*/
}
/**
* Рассчет освещения в точке для дальнейшей интерполяции при отрисовке сглаженного полигона
* @param light
*/
public void light(Vector light) {
if (light != null && !light.isEmpty()) {
k = 0;
int kk;
for (int i = 0; i < light.size(); i++) {
if (light.elementAt(i) == null)
continue;
Light li = (Light) light.elementAt(i);
float lx = xc - li.xc, ly = yc - li.yc, lz = zc - li.zc;
double len = Math.sqrt(lx * lx + ly * ly + lz * lz);
lx /= len;
ly /= len;
lz /= len;
kk = (int) ((lx * rnx + ly * rny + lz * rnz) * 100) << 16;
if (kk > 0)
kk = 0;
kk *= -li.s;
k += kk;
}
} else {
float kk = -rnz;
k = (int) ((kk) * 100) << 16;
}
}
public void move(int a, int b, int c) {
x += a;
y += b;
z += c;
}
public void normalize() {
double length = Math.sqrt(nx * nx + ny * ny + nz * nz);
nx = (float) (nx / ((length == 0D) ? 1D : length));
ny = (float) (ny / ((length == 0D) ? 1D : length));
nz = (float) (nz / ((length == 0D) ? 1D : length));
}
public void soequal() {
x = xc;
y = yc;
z = zc;
}
public void soeqNorm() {
nx = rnx;
ny = rny;
nz = rnz;
}
public static int[] unProject(Matrix3D m, int xs, int ys) { // обратная проекция в 3D
float a = Statics.pers * m.xx - xs * m.zx + Statics.w / 2 * m.zx, b = Statics.pers * m.xz - xs * m.zz + Statics.w / 2 * m.zz;
float c = Statics.pers * m.yx - Statics.h / 2 * m.zx + ys * m.zx, d = Statics.pers * m.yz - Statics.h / 2 * m.zz + ys * m.zz;
float e = xs * m.zo + xs * dist - Statics.w / 2 * m.zo - Statics.w / 2 * dist - Statics.pers * m.xo, f = Statics.h / 2 * m.zo + Statics.h / 2 * dist - ys * m.zo - ys * dist - Statics.pers * m.yo;
return new int[]{(int) ((e * d - b * f) / (a * d - c * b)), (int) ((a * f - c * e) / (a * d - c * b))};
}
}

BIN
src/examples/cubes.s3d Normal file

Binary file not shown.

BIN
src/examples/home.s3d Normal file

Binary file not shown.

BIN
src/examples/logo.s3d Normal file

Binary file not shown.

BIN
src/examples/tank.s3d Normal file

Binary file not shown.

BIN
src/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
src/img/30/Omni.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 780 B

BIN
src/img/30/TargetL.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

BIN
src/img/30/Zoom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
src/img/30/box.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/img/30/brush.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 B

BIN
src/img/30/cone.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
src/img/30/cursor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

BIN
src/img/30/cylinder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
src/img/30/disk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
src/img/30/eye.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/img/30/geom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
src/img/30/modes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
src/img/30/move.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/img/30/moveObj.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/img/30/plane.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
src/img/30/pyramide.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
src/img/30/rotateObj.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/img/30/scaleObj.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/img/30/sel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
src/img/30/sel3d.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
src/img/30/sellist.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
src/img/30/sphere.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
src/img/30/tex.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
src/img/30/torus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
src/img/30/triangle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
src/img/60/Omni.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
src/img/60/Zoom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
src/img/60/box.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
src/img/60/cone.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
src/img/60/cursor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
src/img/60/cylinder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
src/img/60/disk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
src/img/60/eye.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
src/img/60/geom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
src/img/60/modes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
src/img/60/move.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
src/img/60/moveObj.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
src/img/60/plane.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

BIN
src/img/60/pyramide.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
src/img/60/rotateObj.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
src/img/60/scaleObj.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
src/img/60/sel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
src/img/60/sel3d.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
src/img/60/sellist.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
src/img/60/sphere.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
src/img/60/torus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
src/img/60/triangle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB